LCOV - code coverage report
Current view: top level - journal - test-compress-benchmark.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 79 84 94.0 %
Date: 2019-08-23 13:36:53 Functions: 5 5 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 52 84 61.9 %

           Branch data     Line data    Source code
       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_XZ || HAVE_LZ4
      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                 :     200910 : static size_t _permute(size_t x) {
      29                 :            :         size_t residue;
      30                 :            : 
      31         [ +  + ]:     200910 :         if (x >= PRIME)
      32                 :          2 :                 return x;
      33                 :            : 
      34                 :     200908 :         residue = x*x % PRIME;
      35         [ +  + ]:     200908 :         if (x <= PRIME / 2)
      36                 :     146614 :                 return residue;
      37                 :            :         else
      38                 :      54294 :                 return PRIME - residue;
      39                 :            : }
      40                 :            : 
      41                 :     100455 : static size_t permute(size_t x) {
      42                 :     100455 :         return _permute((_permute(x) + arg_start) % MAX_SIZE ^ 0xFF345);
      43                 :            : }
      44                 :            : 
      45                 :         24 : static char* make_buf(size_t count, const char *type) {
      46                 :            :         char *buf;
      47                 :            :         size_t i;
      48                 :            : 
      49                 :         24 :         buf = malloc(count);
      50         [ -  + ]:         24 :         assert_se(buf);
      51                 :            : 
      52         [ +  + ]:         24 :         if (streq(type, "zeros"))
      53         [ +  - ]:          8 :                 memzero(buf, count);
      54         [ +  + ]:         16 :         else if (streq(type, "simple"))
      55         [ +  + ]:    8388616 :                 for (i = 0; i < count; i++)
      56                 :    8388608 :                         buf[i] = 'a' + i % ('z' - 'a' + 1);
      57         [ +  - ]:          8 :         else if (streq(type, "random")) {
      58                 :          8 :                 size_t step = count / 10;
      59                 :            : 
      60                 :          8 :                 random_bytes(buf, step);
      61         [ +  - ]:          8 :                 memzero(buf + 1*step, step);
      62                 :          8 :                 random_bytes(buf + 2*step, step);
      63         [ +  - ]:          8 :                 memzero(buf + 3*step, step);
      64                 :          8 :                 random_bytes(buf + 4*step, step);
      65         [ +  - ]:          8 :                 memzero(buf + 5*step, step);
      66                 :          8 :                 random_bytes(buf + 6*step, step);
      67         [ +  - ]:          8 :                 memzero(buf + 7*step, step);
      68                 :          8 :                 random_bytes(buf + 8*step, step);
      69         [ +  - ]:          8 :                 memzero(buf + 9*step, step);
      70                 :            :         } else
      71                 :          0 :                 assert_not_reached("here");
      72                 :            : 
      73                 :         24 :         return buf;
      74                 :            : }
      75                 :            : 
      76                 :         24 : static void test_compress_decompress(const char* label, const char* type,
      77                 :            :                                      compress_t compress, decompress_t decompress) {
      78                 :         24 :         usec_t n, n2 = 0;
      79                 :            :         float dt;
      80                 :            : 
      81                 :         24 :         _cleanup_free_ char *text, *buf;
      82                 :         48 :         _cleanup_free_ void *buf2 = NULL;
      83                 :         24 :         size_t buf2_allocated = 0;
      84                 :         24 :         size_t skipped = 0, compressed = 0, total = 0;
      85                 :            : 
      86                 :         24 :         text = make_buf(MAX_SIZE, type);
      87                 :         24 :         buf = calloc(MAX_SIZE + 1, 1);
      88   [ +  -  -  + ]:         24 :         assert_se(text && buf);
      89                 :            : 
      90                 :         24 :         n = now(CLOCK_MONOTONIC);
      91                 :            : 
      92         [ +  - ]:     100455 :         for (size_t i = 0; i <= MAX_SIZE; i++) {
      93                 :     100455 :                 size_t j = 0, k = 0, size;
      94                 :            :                 int r;
      95                 :            : 
      96                 :     100455 :                 size = permute(i);
      97         [ -  + ]:     100455 :                 if (size == 0)
      98                 :       3200 :                         continue;
      99                 :            : 
     100         [ -  + ]:     100455 :                 log_debug("%s %zu %zu", type, i, size);
     101                 :            : 
     102         [ +  - ]:     100455 :                 memzero(buf, MIN(size + 1000, MAX_SIZE));
     103                 :            : 
     104                 :     100455 :                 r = compress(text, size, buf, size, &j);
     105                 :            :                 /* assume compression must be successful except for small or random inputs */
     106   [ +  +  +  +  :     100455 :                 assert_se(r == 0 || (size < 2048 && r == -ENOBUFS) || streq(type, "random"));
          -  +  +  +  +  
                +  -  + ]
     107                 :            : 
     108                 :            :                 /* check for overwrites */
     109         [ -  + ]:     100455 :                 assert_se(buf[size] == 0);
     110         [ +  + ]:     100455 :                 if (r != 0) {
     111                 :       3200 :                         skipped += size;
     112                 :       3200 :                         continue;
     113                 :            :                 }
     114                 :            : 
     115         [ -  + ]:      97255 :                 assert_se(j > 0);
     116         [ -  + ]:      97255 :                 if (j >= size)
     117         [ #  # ]:          0 :                         log_error("%s \"compressed\" %zu -> %zu", label, size, j);
     118                 :            : 
     119                 :      97255 :                 r = decompress(buf, j, &buf2, &buf2_allocated, &k, 0);
     120         [ -  + ]:      97255 :                 assert_se(r == 0);
     121         [ -  + ]:      97255 :                 assert_se(buf2_allocated >= k);
     122         [ -  + ]:      97255 :                 assert_se(k == size);
     123                 :            : 
     124         [ -  + ]:      97255 :                 assert_se(memcmp(text, buf2, size) == 0);
     125                 :            : 
     126                 :      97255 :                 total += size;
     127                 :      97255 :                 compressed += j;
     128                 :            : 
     129                 :      97255 :                 n2 = now(CLOCK_MONOTONIC);
     130         [ +  + ]:      97255 :                 if (n2 - n > arg_duration)
     131                 :         24 :                         break;
     132                 :            :         }
     133                 :            : 
     134                 :         24 :         dt = (n2-n) / 1e6;
     135                 :            : 
     136         [ +  - ]:         24 :         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                 :         24 : }
     143                 :            : #endif
     144                 :            : 
     145                 :          4 : int main(int argc, char *argv[]) {
     146                 :            : #if HAVE_XZ || HAVE_LZ4
     147                 :          4 :         test_setup_logging(LOG_INFO);
     148                 :            : 
     149         [ -  + ]:          4 :         if (argc >= 2) {
     150                 :            :                 unsigned x;
     151                 :            : 
     152         [ #  # ]:          0 :                 assert_se(safe_atou(argv[1], &x) >= 0);
     153                 :          0 :                 arg_duration = x * USEC_PER_SEC;
     154                 :            :         } else
     155                 :          8 :                 arg_duration = slow_tests_enabled() ?
     156         [ +  - ]:          4 :                         2 * USEC_PER_SEC : USEC_PER_SEC / 50;
     157                 :            : 
     158         [ -  + ]:          4 :         if (argc == 3)
     159                 :          0 :                 (void) safe_atozu(argv[2], &arg_start);
     160                 :            :         else
     161                 :          4 :                 arg_start = getpid_cached();
     162                 :            : 
     163                 :            :         const char *i;
     164   [ +  -  +  + ]:         16 :         NULSTR_FOREACH(i, "zeros\0simple\0random\0") {
     165                 :            : #if HAVE_XZ
     166                 :         12 :                 test_compress_decompress("XZ", i, compress_blob_xz, decompress_blob_xz);
     167                 :            : #endif
     168                 :            : #if HAVE_LZ4
     169                 :         12 :                 test_compress_decompress("LZ4", i, compress_blob_lz4, decompress_blob_lz4);
     170                 :            : #endif
     171                 :            :         }
     172                 :          4 :         return 0;
     173                 :            : #else
     174                 :            :         return log_tests_skipped("No compression feature is enabled");
     175                 :            : #endif
     176                 :            : }

Generated by: LCOV version 1.14