]>
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" |
fd53fee0 | 22 | #include "macro.h" |
6bedfcbb | 23 | #include "parse-util.h" |
9f35e8b4 | 24 | #include "random-util.h" |
07630cea LP |
25 | #include "string-util.h" |
26 | #include "util.h" | |
fd53fee0 | 27 | |
5d6f46b6 ZJS |
28 | typedef int (compress_t)(const void *src, uint64_t src_size, void *dst, |
29 | size_t dst_alloc_size, size_t *dst_size); | |
fd53fee0 | 30 | typedef int (decompress_t)(const void *src, uint64_t src_size, |
fa1c4b51 | 31 | void **dst, size_t *dst_alloc_size, size_t* dst_size, size_t dst_max); |
fd53fee0 | 32 | |
c4291c15 ZJS |
33 | static usec_t arg_duration = 2 * USEC_PER_SEC; |
34 | static size_t arg_start; | |
35 | ||
fd53fee0 | 36 | #define MAX_SIZE (1024*1024LU) |
c4291c15 ZJS |
37 | #define PRIME 1048571 /* A prime close enough to one megabyte that mod 4 == 3 */ |
38 | ||
39 | static size_t _permute(size_t x) { | |
40 | size_t residue; | |
41 | ||
42 | if (x >= PRIME) | |
43 | return x; | |
44 | ||
45 | residue = x*x % PRIME; | |
46 | if (x <= PRIME / 2) | |
47 | return residue; | |
48 | else | |
49 | return PRIME - residue; | |
50 | } | |
51 | ||
52 | static size_t permute(size_t x) { | |
53 | return _permute((_permute(x) + arg_start) % MAX_SIZE ^ 0xFF345); | |
54 | } | |
fd53fee0 | 55 | |
9f35e8b4 | 56 | static char* make_buf(size_t count, const char *type) { |
fd53fee0 ZJS |
57 | char *buf; |
58 | size_t i; | |
59 | ||
60 | buf = malloc(count); | |
0c0cdb06 | 61 | assert_se(buf); |
fd53fee0 | 62 | |
9f35e8b4 ZJS |
63 | if (streq(type, "zeros")) |
64 | memzero(buf, count); | |
65 | else if (streq(type, "simple")) | |
66 | for (i = 0; i < count; i++) | |
67 | buf[i] = 'a' + i % ('z' - 'a' + 1); | |
68 | else if (streq(type, "random")) { | |
0036b0bf ZJS |
69 | size_t step = count / 10; |
70 | ||
71 | random_bytes(buf, step); | |
72 | memzero(buf + 1*step, step); | |
73 | random_bytes(buf + 2*step, step); | |
74 | memzero(buf + 3*step, step); | |
75 | random_bytes(buf + 4*step, step); | |
76 | memzero(buf + 5*step, step); | |
77 | random_bytes(buf + 6*step, step); | |
78 | memzero(buf + 7*step, step); | |
79 | random_bytes(buf + 8*step, step); | |
80 | memzero(buf + 9*step, step); | |
9f35e8b4 ZJS |
81 | } else |
82 | assert_not_reached("here"); | |
fd53fee0 ZJS |
83 | |
84 | return buf; | |
85 | } | |
86 | ||
9f35e8b4 | 87 | static void test_compress_decompress(const char* label, const char* type, |
fd53fee0 | 88 | compress_t compress, decompress_t decompress) { |
da2e1c71 | 89 | usec_t n, n2 = 0; |
fd53fee0 ZJS |
90 | float dt; |
91 | ||
92 | _cleanup_free_ char *text, *buf; | |
93 | _cleanup_free_ void *buf2 = NULL; | |
fa1c4b51 | 94 | size_t buf2_allocated = 0; |
fd53fee0 ZJS |
95 | size_t skipped = 0, compressed = 0, total = 0; |
96 | ||
9f35e8b4 | 97 | text = make_buf(MAX_SIZE, type); |
fd53fee0 | 98 | buf = calloc(MAX_SIZE + 1, 1); |
0c0cdb06 | 99 | assert_se(text && buf); |
fd53fee0 ZJS |
100 | |
101 | n = now(CLOCK_MONOTONIC); | |
102 | ||
c4291c15 ZJS |
103 | for (size_t i = 0; i <= MAX_SIZE; i++) { |
104 | size_t j = 0, k = 0, size; | |
fd53fee0 ZJS |
105 | int r; |
106 | ||
c4291c15 | 107 | size = permute(i); |
15b947fb ZJS |
108 | if (size == 0) |
109 | continue; | |
c4291c15 ZJS |
110 | |
111 | log_debug("%s %zu %zu", type, i, size); | |
112 | ||
113 | memzero(buf, MIN(size + 1000, MAX_SIZE)); | |
114 | ||
5d6f46b6 ZJS |
115 | r = compress(text, size, buf, size, &j); |
116 | /* assume compression must be successful except for small or random inputs */ | |
c4291c15 | 117 | assert_se(r == 0 || (size < 2048 && r == -ENOBUFS) || streq(type, "random")); |
9f35e8b4 | 118 | |
fd53fee0 | 119 | /* check for overwrites */ |
c4291c15 | 120 | assert_se(buf[size] == 0); |
fd53fee0 | 121 | if (r != 0) { |
c4291c15 | 122 | skipped += size; |
fd53fee0 ZJS |
123 | continue; |
124 | } | |
125 | ||
0c0cdb06 | 126 | assert_se(j > 0); |
c4291c15 ZJS |
127 | if (j >= size) |
128 | log_error("%s \"compressed\" %zu -> %zu", label, size, j); | |
fd53fee0 ZJS |
129 | |
130 | r = decompress(buf, j, &buf2, &buf2_allocated, &k, 0); | |
0c0cdb06 RC |
131 | assert_se(r == 0); |
132 | assert_se(buf2_allocated >= k); | |
c4291c15 | 133 | assert_se(k == size); |
fd53fee0 | 134 | |
c4291c15 | 135 | assert_se(memcmp(text, buf2, size) == 0); |
fd53fee0 | 136 | |
c4291c15 | 137 | total += size; |
fd53fee0 ZJS |
138 | compressed += j; |
139 | ||
140 | n2 = now(CLOCK_MONOTONIC); | |
c4291c15 | 141 | if (n2 - n > arg_duration) |
fd53fee0 ZJS |
142 | break; |
143 | } | |
144 | ||
145 | dt = (n2-n) / 1e6; | |
146 | ||
9f35e8b4 | 147 | log_info("%s/%s: compressed & decompressed %zu bytes in %.2fs (%.2fMiB/s), " |
fd53fee0 | 148 | "mean compresion %.2f%%, skipped %zu bytes", |
9f35e8b4 | 149 | label, type, total, dt, |
fd53fee0 ZJS |
150 | total / 1024. / 1024 / dt, |
151 | 100 - compressed * 100. / total, | |
152 | skipped); | |
153 | } | |
154 | ||
155 | int main(int argc, char *argv[]) { | |
9f35e8b4 | 156 | const char *i; |
fd53fee0 | 157 | |
c4291c15 ZJS |
158 | log_set_max_level(LOG_INFO); |
159 | ||
160 | if (argc >= 2) { | |
161 | unsigned x; | |
162 | ||
163 | assert_se(safe_atou(argv[1], &x) >= 0); | |
164 | arg_duration = x * USEC_PER_SEC; | |
165 | } | |
166 | if (argc == 3) | |
7c2da2ca | 167 | (void) safe_atozu(argv[2], &arg_start); |
c4291c15 ZJS |
168 | else |
169 | arg_start = getpid(); | |
fd53fee0 | 170 | |
9f35e8b4 | 171 | NULSTR_FOREACH(i, "zeros\0simple\0random\0") { |
fd53fee0 | 172 | #ifdef HAVE_XZ |
9f35e8b4 | 173 | test_compress_decompress("XZ", i, compress_blob_xz, decompress_blob_xz); |
fd53fee0 ZJS |
174 | #endif |
175 | #ifdef HAVE_LZ4 | |
9f35e8b4 | 176 | test_compress_decompress("LZ4", i, compress_blob_lz4, decompress_blob_lz4); |
fd53fee0 | 177 | #endif |
9f35e8b4 | 178 | } |
fd53fee0 ZJS |
179 | return 0; |
180 | } |