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