test-compress-benchmark.c revision c4291c1524ee4e4575c3b0a726ca5507b2ba74f3
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering/***
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering This file is part of systemd
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering Copyright 2014 Zbigniew Jędrzejewski-Szmek
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering systemd is free software; you can redistribute it and/or modify it
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering under the terms of the GNU Lesser General Public License as published by
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering (at your option) any later version.
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering systemd is distributed in the hope that it will be useful, but
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering Lesser General Public License for more details.
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering You should have received a copy of the GNU Lesser General Public License
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering***/
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#include "compress.h"
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#include "util.h"
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#include "macro.h"
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#include "random-util.h"
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poetteringtypedef int (compress_t)(const void *src, uint64_t src_size, void *dst, size_t *dst_size);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poetteringtypedef int (decompress_t)(const void *src, uint64_t src_size,
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering void **dst, size_t *dst_alloc_size, size_t* dst_size, size_t dst_max);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poetteringstatic usec_t arg_duration = 2 * USEC_PER_SEC;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poetteringstatic size_t arg_start;
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#define MAX_SIZE (1024*1024LU)
bb99a35a873c35e80b0b47fe045081022660374dLennart Poettering#define PRIME 1048571 /* A prime close enough to one megabyte that mod 4 == 3 */
bb99a35a873c35e80b0b47fe045081022660374dLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poetteringstatic size_t _permute(size_t x) {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering size_t residue;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (x >= PRIME)
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering return x;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering residue = x*x % PRIME;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (x <= PRIME / 2)
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering return residue;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering else
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering return PRIME - residue;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering}
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poetteringstatic size_t permute(size_t x) {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering return _permute((_permute(x) + arg_start) % MAX_SIZE ^ 0xFF345);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering}
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
bb99a35a873c35e80b0b47fe045081022660374dLennart Poetteringstatic char* make_buf(size_t count, const char *type) {
bb99a35a873c35e80b0b47fe045081022660374dLennart Poettering char *buf;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering size_t i;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering buf = malloc(count);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering assert_se(buf);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (streq(type, "zeros"))
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering memzero(buf, count);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering else if (streq(type, "simple"))
a5344d2c3b0f14e954ce1c0ef905c5b44bc5bf0aLennart Poettering for (i = 0; i < count; i++)
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering buf[i] = 'a' + i % ('z' - 'a' + 1);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering else if (streq(type, "random")) {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering random_bytes(buf, count/10);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering random_bytes(buf + 2*count/10, count/10);
d0bbc21caa6e68693a47db60c93e99422bf2a858Lennart Poettering random_bytes(buf + 4*count/10, count/20);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering random_bytes(buf + 6*count/10, count/20);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering random_bytes(buf + 8*count/10, count/20);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering } else
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering assert_not_reached("here");
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
a5344d2c3b0f14e954ce1c0ef905c5b44bc5bf0aLennart Poettering return buf;
d0bbc21caa6e68693a47db60c93e99422bf2a858Lennart Poettering}
d0bbc21caa6e68693a47db60c93e99422bf2a858Lennart Poettering
d0bbc21caa6e68693a47db60c93e99422bf2a858Lennart Poetteringstatic void test_compress_decompress(const char* label, const char* type,
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering compress_t compress, decompress_t decompress) {
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering usec_t n, n2 = 0;
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering float dt;
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering _cleanup_free_ char *text, *buf;
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering _cleanup_free_ void *buf2 = NULL;
d0bbc21caa6e68693a47db60c93e99422bf2a858Lennart Poettering size_t buf2_allocated = 0;
d0bbc21caa6e68693a47db60c93e99422bf2a858Lennart Poettering size_t skipped = 0, compressed = 0, total = 0;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering text = make_buf(MAX_SIZE, type);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering buf = calloc(MAX_SIZE + 1, 1);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering assert_se(text && buf);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering n = now(CLOCK_MONOTONIC);
d0bbc21caa6e68693a47db60c93e99422bf2a858Lennart Poettering
d0bbc21caa6e68693a47db60c93e99422bf2a858Lennart Poettering for (size_t i = 0; i <= MAX_SIZE; i++) {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering size_t j = 0, k = 0, size;
d0bbc21caa6e68693a47db60c93e99422bf2a858Lennart Poettering int r;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering size = permute(i);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering log_debug("%s %zu %zu", type, i, size);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering memzero(buf, MIN(size + 1000, MAX_SIZE));
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering r = compress(text, size, buf, &j);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering /* assume compression must be successful except for small inputs */
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering assert_se(r == 0 || (size < 2048 && r == -ENOBUFS) || streq(type, "random"));
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering /* check for overwrites */
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering assert_se(buf[size] == 0);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering if (r != 0) {
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering skipped += size;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering continue;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering }
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering assert_se(j > 0);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering if (j >= size)
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering log_error("%s \"compressed\" %zu -> %zu", label, size, j);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering r = decompress(buf, j, &buf2, &buf2_allocated, &k, 0);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering assert_se(r == 0);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering assert_se(buf2_allocated >= k);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering assert_se(k == size);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering assert_se(memcmp(text, buf2, size) == 0);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering total += size;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering compressed += j;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering n2 = now(CLOCK_MONOTONIC);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (n2 - n > arg_duration)
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering break;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering }
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering dt = (n2-n) / 1e6;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering log_info("%s/%s: compressed & decompressed %zu bytes in %.2fs (%.2fMiB/s), "
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering "mean compresion %.2f%%, skipped %zu bytes",
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering label, type, total, dt,
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering total / 1024. / 1024 / dt,
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering 100 - compressed * 100. / total,
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering skipped);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering}
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poetteringint main(int argc, char *argv[]) {
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering const char *i;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering log_set_max_level(LOG_INFO);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering if (argc >= 2) {
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering unsigned x;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering assert_se(safe_atou(argv[1], &x) >= 0);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering arg_duration = x * USEC_PER_SEC;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering }
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering if (argc == 3)
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering (void) safe_atolu(argv[2], &arg_start);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering else
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering arg_start = getpid();
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering NULSTR_FOREACH(i, "zeros\0simple\0random\0") {
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering#ifdef HAVE_XZ
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering test_compress_decompress("XZ", i, compress_blob_xz, decompress_blob_xz);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering#endif
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering#ifdef HAVE_LZ4
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering test_compress_decompress("LZ4", i, compress_blob_lz4, decompress_blob_lz4);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#endif
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering }
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering return 0;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering}
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering