]>
Commit | Line | Data |
---|---|---|
fd53fee0 ZJS |
1 | /*** |
2 | This file is part of systemd | |
3 | ||
4 | Copyright 2014 Zbigniew Jędrzejewski-Szmek | |
5 | ||
6 | systemd is free software; you can redistribute it and/or modify it | |
7 | under the terms of the GNU Lesser General Public License as published by | |
8 | the Free Software Foundation; either version 2.1 of the License, or | |
9 | (at your option) any later version. | |
10 | ||
11 | systemd is distributed in the hope that it will be useful, but | |
12 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | Lesser General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU Lesser General Public License | |
17 | along with systemd; If not, see <http://www.gnu.org/licenses/>. | |
18 | ***/ | |
19 | ||
b5efdb8a | 20 | #include "alloc-util.h" |
fd53fee0 | 21 | #include "compress.h" |
245d3d3c | 22 | #include "env-util.h" |
fd53fee0 | 23 | #include "macro.h" |
6bedfcbb | 24 | #include "parse-util.h" |
9f35e8b4 | 25 | #include "random-util.h" |
07630cea LP |
26 | #include "string-util.h" |
27 | #include "util.h" | |
fd53fee0 | 28 | |
5d6f46b6 ZJS |
29 | typedef int (compress_t)(const void *src, uint64_t src_size, void *dst, |
30 | size_t dst_alloc_size, size_t *dst_size); | |
fd53fee0 | 31 | typedef int (decompress_t)(const void *src, uint64_t src_size, |
fa1c4b51 | 32 | void **dst, size_t *dst_alloc_size, size_t* dst_size, size_t dst_max); |
fd53fee0 | 33 | |
349cc4a5 | 34 | #if HAVE_XZ || HAVE_LZ4 |
ccc717fa | 35 | |
245d3d3c | 36 | static usec_t arg_duration; |
c4291c15 ZJS |
37 | static size_t arg_start; |
38 | ||
fd53fee0 | 39 | #define MAX_SIZE (1024*1024LU) |
c4291c15 ZJS |
40 | #define PRIME 1048571 /* A prime close enough to one megabyte that mod 4 == 3 */ |
41 | ||
42 | static size_t _permute(size_t x) { | |
43 | size_t residue; | |
44 | ||
45 | if (x >= PRIME) | |
46 | return x; | |
47 | ||
48 | residue = x*x % PRIME; | |
49 | if (x <= PRIME / 2) | |
50 | return residue; | |
51 | else | |
52 | return PRIME - residue; | |
53 | } | |
54 | ||
55 | static size_t permute(size_t x) { | |
56 | return _permute((_permute(x) + arg_start) % MAX_SIZE ^ 0xFF345); | |
57 | } | |
fd53fee0 | 58 | |
9f35e8b4 | 59 | static char* make_buf(size_t count, const char *type) { |
fd53fee0 ZJS |
60 | char *buf; |
61 | size_t i; | |
62 | ||
63 | buf = malloc(count); | |
0c0cdb06 | 64 | assert_se(buf); |
fd53fee0 | 65 | |
9f35e8b4 ZJS |
66 | if (streq(type, "zeros")) |
67 | memzero(buf, count); | |
68 | else if (streq(type, "simple")) | |
69 | for (i = 0; i < count; i++) | |
70 | buf[i] = 'a' + i % ('z' - 'a' + 1); | |
71 | else if (streq(type, "random")) { | |
0036b0bf ZJS |
72 | size_t step = count / 10; |
73 | ||
74 | random_bytes(buf, step); | |
75 | memzero(buf + 1*step, step); | |
76 | random_bytes(buf + 2*step, step); | |
77 | memzero(buf + 3*step, step); | |
78 | random_bytes(buf + 4*step, step); | |
79 | memzero(buf + 5*step, step); | |
80 | random_bytes(buf + 6*step, step); | |
81 | memzero(buf + 7*step, step); | |
82 | random_bytes(buf + 8*step, step); | |
83 | memzero(buf + 9*step, step); | |
9f35e8b4 ZJS |
84 | } else |
85 | assert_not_reached("here"); | |
fd53fee0 ZJS |
86 | |
87 | return buf; | |
88 | } | |
89 | ||
9f35e8b4 | 90 | static void test_compress_decompress(const char* label, const char* type, |
fd53fee0 | 91 | compress_t compress, decompress_t decompress) { |
da2e1c71 | 92 | usec_t n, n2 = 0; |
fd53fee0 ZJS |
93 | float dt; |
94 | ||
95 | _cleanup_free_ char *text, *buf; | |
96 | _cleanup_free_ void *buf2 = NULL; | |
fa1c4b51 | 97 | size_t buf2_allocated = 0; |
fd53fee0 ZJS |
98 | size_t skipped = 0, compressed = 0, total = 0; |
99 | ||
9f35e8b4 | 100 | text = make_buf(MAX_SIZE, type); |
fd53fee0 | 101 | buf = calloc(MAX_SIZE + 1, 1); |
0c0cdb06 | 102 | assert_se(text && buf); |
fd53fee0 ZJS |
103 | |
104 | n = now(CLOCK_MONOTONIC); | |
105 | ||
c4291c15 ZJS |
106 | for (size_t i = 0; i <= MAX_SIZE; i++) { |
107 | size_t j = 0, k = 0, size; | |
fd53fee0 ZJS |
108 | int r; |
109 | ||
c4291c15 | 110 | size = permute(i); |
15b947fb ZJS |
111 | if (size == 0) |
112 | continue; | |
c4291c15 ZJS |
113 | |
114 | log_debug("%s %zu %zu", type, i, size); | |
115 | ||
116 | memzero(buf, MIN(size + 1000, MAX_SIZE)); | |
117 | ||
5d6f46b6 ZJS |
118 | r = compress(text, size, buf, size, &j); |
119 | /* assume compression must be successful except for small or random inputs */ | |
c4291c15 | 120 | assert_se(r == 0 || (size < 2048 && r == -ENOBUFS) || streq(type, "random")); |
9f35e8b4 | 121 | |
fd53fee0 | 122 | /* check for overwrites */ |
c4291c15 | 123 | assert_se(buf[size] == 0); |
fd53fee0 | 124 | if (r != 0) { |
c4291c15 | 125 | skipped += size; |
fd53fee0 ZJS |
126 | continue; |
127 | } | |
128 | ||
0c0cdb06 | 129 | assert_se(j > 0); |
c4291c15 ZJS |
130 | if (j >= size) |
131 | log_error("%s \"compressed\" %zu -> %zu", label, size, j); | |
fd53fee0 ZJS |
132 | |
133 | r = decompress(buf, j, &buf2, &buf2_allocated, &k, 0); | |
0c0cdb06 RC |
134 | assert_se(r == 0); |
135 | assert_se(buf2_allocated >= k); | |
c4291c15 | 136 | assert_se(k == size); |
fd53fee0 | 137 | |
c4291c15 | 138 | assert_se(memcmp(text, buf2, size) == 0); |
fd53fee0 | 139 | |
c4291c15 | 140 | total += size; |
fd53fee0 ZJS |
141 | compressed += j; |
142 | ||
143 | n2 = now(CLOCK_MONOTONIC); | |
c4291c15 | 144 | if (n2 - n > arg_duration) |
fd53fee0 ZJS |
145 | break; |
146 | } | |
147 | ||
148 | dt = (n2-n) / 1e6; | |
149 | ||
9f35e8b4 | 150 | log_info("%s/%s: compressed & decompressed %zu bytes in %.2fs (%.2fMiB/s), " |
fd53fee0 | 151 | "mean compresion %.2f%%, skipped %zu bytes", |
9f35e8b4 | 152 | label, type, total, dt, |
fd53fee0 ZJS |
153 | total / 1024. / 1024 / dt, |
154 | 100 - compressed * 100. / total, | |
155 | skipped); | |
156 | } | |
ccc717fa | 157 | #endif |
fd53fee0 ZJS |
158 | |
159 | int main(int argc, char *argv[]) { | |
349cc4a5 | 160 | #if HAVE_XZ || HAVE_LZ4 |
9f35e8b4 | 161 | const char *i; |
245d3d3c | 162 | int r; |
fd53fee0 | 163 | |
c4291c15 ZJS |
164 | log_set_max_level(LOG_INFO); |
165 | ||
166 | if (argc >= 2) { | |
167 | unsigned x; | |
168 | ||
169 | assert_se(safe_atou(argv[1], &x) >= 0); | |
170 | arg_duration = x * USEC_PER_SEC; | |
245d3d3c ZJS |
171 | } else { |
172 | bool slow; | |
173 | ||
174 | r = getenv_bool("SYSTEMD_SLOW_TESTS"); | |
175 | slow = r >= 0 ? r : SYSTEMD_SLOW_TESTS_DEFAULT; | |
176 | ||
177 | arg_duration = slow ? 2 * USEC_PER_SEC : USEC_PER_SEC / 50; | |
c4291c15 | 178 | } |
245d3d3c | 179 | |
c4291c15 | 180 | if (argc == 3) |
7c2da2ca | 181 | (void) safe_atozu(argv[2], &arg_start); |
c4291c15 | 182 | else |
df0ff127 | 183 | arg_start = getpid_cached(); |
fd53fee0 | 184 | |
9f35e8b4 | 185 | NULSTR_FOREACH(i, "zeros\0simple\0random\0") { |
349cc4a5 | 186 | #if HAVE_XZ |
9f35e8b4 | 187 | test_compress_decompress("XZ", i, compress_blob_xz, decompress_blob_xz); |
fd53fee0 | 188 | #endif |
349cc4a5 | 189 | #if HAVE_LZ4 |
9f35e8b4 | 190 | test_compress_decompress("LZ4", i, compress_blob_lz4, decompress_blob_lz4); |
fd53fee0 | 191 | #endif |
9f35e8b4 | 192 | } |
fd53fee0 | 193 | return 0; |
ccc717fa ZJS |
194 | #else |
195 | return EXIT_TEST_SKIP; | |
196 | #endif | |
fd53fee0 | 197 | } |