Created
May 11, 2015 21:30
-
-
Save dajhorn/793c64d3fe77069fb1e0 to your computer and use it in GitHub Desktop.
Tinc compression benchmark, updated for the liblz4 head.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
compression.c -- compression benchmark | |
Copyright (C) 2015 Guus Sliepen <[email protected]> | |
Compile: gcc -std=gnu99 compression_speed.c -lz -llzo2 -llz4 -lrt | |
Usage: compression_speed [packet size] < input | |
This program is free software; you can redistribute it and/or modify | |
it under the terms of the GNU General Public License as published by | |
the Free Software Foundation; either version 2 of the License, or | |
(at your option) any later version. | |
This program is distributed in the hope that it will be useful, | |
but WITHOUT ANY WARRANTY; without even the implied warranty of | |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
GNU General Public License for more details. | |
You should have received a copy of the GNU General Public License along | |
with this program; if not, write to the Free Software Foundation, Inc., | |
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
*/ | |
#include <stdlib.h> | |
#include <stdbool.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <stdio.h> | |
#include <time.h> | |
#include <zlib.h> | |
#include <lzo/lzo1x.h> | |
#include <lz4.h> | |
#include <lz4hc.h> | |
struct timespec start; | |
struct timespec end; | |
static void clock_start() { | |
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start); | |
} | |
static double clock_end() { | |
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end); | |
return end.tv_sec + end.tv_nsec * 1e-9 - start.tv_sec - start.tv_nsec * 1e-9; | |
} | |
static char lzo_wrkmem[LZO1X_999_MEM_COMPRESS > LZO1X_1_MEM_COMPRESS ? LZO1X_999_MEM_COMPRESS : LZO1X_1_MEM_COMPRESS]; | |
static void *lz4_wrkmem; | |
static ssize_t do_compress(int level, const void *in, size_t inlen, void *out, size_t maxlen) { | |
if(level <= 9) { | |
unsigned long outlen = maxlen; | |
if(compress2(out, &outlen, in, inlen, level) != Z_OK) | |
return -1; | |
return outlen; | |
} else if(level <= 11) { | |
lzo_uint outlen = maxlen; | |
int result; | |
if(level == 10) | |
result = lzo1x_1_compress(in, inlen, out, &outlen, lzo_wrkmem); | |
else | |
result = lzo1x_999_compress(in, inlen, out, &outlen, lzo_wrkmem); | |
if(result != LZO_E_OK) | |
return -1; | |
return outlen; | |
} else if(level <= 13) { | |
/* LZ4 release 1.7.0 legacy interface. */ | |
int outlen; | |
if(level == 12) | |
outlen = LZ4_compress_limitedOutput(in, out, inlen, maxlen); | |
else | |
outlen = LZ4_compressHC_limitedOutput(in, out, inlen, maxlen); | |
return outlen; | |
} else if(level <= 15) { | |
/* LZ4 head r129 */ | |
if(level == 14) | |
/* LZ4_compress_default() level. */ | |
return LZ4_compress_fast_extState(lz4_wrkmem, in, out, inlen, maxlen, 1); | |
else if (level == 15) | |
/* New liblz4 default level. */ | |
return LZ4_compress_fast_extState(lz4_wrkmem, in, out, inlen, maxlen, 0); | |
} | |
} | |
static ssize_t do_decompress(int level, const void *in, size_t inlen, void *out, size_t maxlen) { | |
if(level <= 9) { | |
unsigned long outlen = maxlen; | |
if(uncompress(out, &outlen, in, inlen) != Z_OK) | |
return -1; | |
return outlen; | |
} else if(level <= 11) { | |
lzo_uint outlen = maxlen; | |
int result; | |
result = lzo1x_decompress_safe(in, inlen, out, &outlen, lzo_wrkmem); | |
if(result != LZO_E_OK) | |
return -1; | |
return outlen; | |
} else if(level <= 15) { | |
return LZ4_decompress_safe(in, out, inlen, maxlen); | |
} | |
} | |
int main(int argc, char *argv[]) { | |
fprintf(stderr, "Reading input from stdin... "); | |
size_t datalen = 0; | |
size_t alloced = 1e6; | |
char *data = malloc(alloced); | |
lz4_wrkmem = malloc(LZ4_sizeofState()); | |
if(!data) | |
abort(); | |
ssize_t len; | |
while((len = read(0, data + datalen, alloced - datalen)) > 0) { | |
datalen += len; | |
if(datalen >= alloced) { | |
alloced += 1e6; | |
data = realloc(data, alloced); | |
if(!data) | |
abort(); | |
} | |
} | |
if(!datalen) | |
return 1; | |
fprintf(stderr, "%zu bytes\n", datalen); | |
lzo_init(); | |
const size_t psize = argc > 1 ? atoi(argv[1]) : 1451; | |
fprintf(stderr, "Packet size: %zu\n", psize); | |
char buf1[psize * 2 + 1024]; | |
char buf2[psize * 2 + 1024]; | |
for(int level = 1; level <= 15; level++) { | |
if(level <= 9) | |
fprintf(stderr, "zlib%d: ", level); | |
else if(level <= 11) | |
fprintf(stderr, "lzo1x_%s ", (level == 11) ? "999: " : "1: "); | |
else if(level <= 13) | |
// Old LZ4. | |
fprintf(stderr, "lz4_%s ", (level == 13) ? "hc: " : "lo: "); | |
else if(level <= 15) | |
// New LZ4. | |
fprintf(stderr, "lz4_%s ", (level == 15) ? "acc:" : "ext:"); | |
// warmup, ignore any errors. | |
for(const char *p = data; p < data + datalen - psize; p += psize) { | |
ssize_t len1 = do_compress(level, p, psize, buf1, sizeof buf1); | |
if(len1 > 0) | |
do_decompress(level, buf1, len1, buf2, sizeof buf2); | |
} | |
// real run | |
size_t ulen = 0; | |
size_t clen = 0; | |
clock_start(); | |
for(const char *p = data; p < data + datalen - psize; p += psize) { | |
ssize_t len1 = do_compress(level, p, psize, buf1, sizeof buf1); | |
if(len1 <= 0) { | |
fprintf(stderr, "compression failed\n"); | |
return 2; | |
} | |
ssize_t len2 = do_decompress(level, buf1, len1, buf2, sizeof buf2); | |
if(len2 <= 0) { | |
fprintf(stderr, "decompression failed\n"); | |
return 3; | |
} | |
if(len2 != psize) { | |
fprintf(stderr, "decompressed size does not match input\n"); | |
return 4; | |
} | |
#if 0 | |
if(memcmp(p, buf2, psize)) { | |
fprintf(stderr, "decompressed data does not match input\n"); | |
return 5; | |
} | |
#endif | |
ulen += psize; | |
clen += len1; | |
} | |
double elapsed = clock_end(); | |
fprintf(stderr, "%6.2lf MB/s, ratio %.2lf\n", ulen / elapsed * 1e-6, (double)clen / ulen); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment