]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-compress-benchmark.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 #include "alloc-util.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"
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_size
, size_t dst_max
);
22 static usec_t arg_duration
;
23 static size_t arg_start
;
25 #define MAX_SIZE (1024*1024LU)
26 #define PRIME 1048571 /* A prime close enough to one megabyte that mod 4 == 3 */
28 static size_t _permute(size_t x
) {
34 residue
= x
*x
% PRIME
;
38 return PRIME
- residue
;
41 static size_t permute(size_t x
) {
42 return _permute((_permute(x
) + arg_start
) % MAX_SIZE
^ 0xFF345);
45 static char* make_buf(size_t count
, const char *type
) {
52 if (streq(type
, "zeros"))
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;
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
);
76 static void test_compress_decompress(const char* label
, const char* type
,
77 compress_t compress
, decompress_t decompress
) {
81 _cleanup_free_
char *text
, *buf
;
82 _cleanup_free_
void *buf2
= NULL
;
83 size_t skipped
= 0, compressed
= 0, total
= 0;
85 text
= make_buf(MAX_SIZE
, type
);
86 buf
= calloc(MAX_SIZE
+ 1, 1);
87 assert_se(text
&& buf
);
89 n
= now(CLOCK_MONOTONIC
);
91 for (size_t i
= 0; i
<= MAX_SIZE
; i
++) {
92 size_t j
= 0, k
= 0, size
;
99 log_debug("%s %zu %zu", type
, i
, size
);
101 memzero(buf
, MIN(size
+ 1000, MAX_SIZE
));
103 r
= compress(text
, size
, buf
, size
, &j
);
104 /* assume compression must be successful except for small or random inputs */
105 assert_se(r
>= 0 || (size
< 2048 && r
== -ENOBUFS
) || streq(type
, "random"));
107 /* check for overwrites */
108 assert_se(buf
[size
] == 0);
116 log_error("%s \"compressed\" %zu -> %zu", label
, size
, j
);
118 r
= decompress(buf
, j
, &buf2
, &k
, 0);
120 assert_se(k
== size
);
122 assert_se(memcmp(text
, buf2
, size
) == 0);
127 n2
= now(CLOCK_MONOTONIC
);
128 if (n2
- n
> arg_duration
)
134 log_info("%s/%s: compressed & decompressed %zu bytes in %.2fs (%.2fMiB/s), "
135 "mean compression %.2f%%, skipped %zu bytes",
136 label
, type
, total
, dt
,
137 total
/ 1024. / 1024 / dt
,
138 100 - compressed
* 100. / total
,
143 int main(int argc
, char *argv
[]) {
145 test_setup_logging(LOG_INFO
);
150 assert_se(safe_atou(argv
[1], &x
) >= 0);
151 arg_duration
= x
* USEC_PER_SEC
;
153 arg_duration
= slow_tests_enabled() ?
154 2 * USEC_PER_SEC
: USEC_PER_SEC
/ 50;
157 (void) safe_atozu(argv
[2], &arg_start
);
159 arg_start
= getpid_cached();
161 NULSTR_FOREACH(i
, "zeros\0simple\0random\0") {
163 test_compress_decompress("XZ", i
, compress_blob_xz
, decompress_blob_xz
);
166 test_compress_decompress("LZ4", i
, compress_blob_lz4
, decompress_blob_lz4
);
169 test_compress_decompress("ZSTD", i
, compress_blob_zstd
, decompress_blob_zstd
);
174 return log_tests_skipped("No compression feature is enabled");