]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/journal/test-compress-benchmark.c
util-lib: split our string related calls from util.[ch] into its own file string...
[thirdparty/systemd.git] / src / journal / test-compress-benchmark.c
CommitLineData
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 28typedef int (compress_t)(const void *src, uint64_t src_size, void *dst, size_t *dst_size);
fd53fee0 29typedef 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
32static usec_t arg_duration = 2 * USEC_PER_SEC;
33static 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
38static 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
51static size_t permute(size_t x) {
52 return _permute((_permute(x) + arg_start) % MAX_SIZE ^ 0xFF345);
53}
fd53fee0 54
9f35e8b4 55static 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 86static 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
152int 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}