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