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