Be able to test and bench the libdeflate library
name old speed new speed delta
wuffs_adler32_10k/clang9 11.4GB/s ± 2% 11.6GB/s ± 2% +1.26% (p=0.013 n=9+10)
wuffs_adler32_100k/clang9 13.7GB/s ± 1% 13.6GB/s ± 1% ~ (p=0.277 n=8+9)
wuffs_adler32_10k/gcc10 12.2GB/s ± 0% 11.4GB/s ± 1% -7.01% (p=0.000 n=8+9)
wuffs_adler32_100k/gcc10 12.0GB/s ± 1% 11.7GB/s ± 1% -2.80% (p=0.000 n=9+9)
mimic_adler32_10k 1.91GB/s ± 0% 25.24GB/s ± 1% +1218.88% (p=0.000 n=9+9)
mimic_adler32_100k 1.87GB/s ± 0% 22.94GB/s ± 1% +1126.66% (p=0.000 n=10+10)
wuffs_crc32_ieee_10k/clang9 7.81GB/s ± 0% 7.70GB/s ± 0% -1.41% (p=0.000 n=8+8)
wuffs_crc32_ieee_100k/clang9 10.0GB/s ± 2% 10.6GB/s ± 1% +5.25% (p=0.000 n=7+8)
wuffs_crc32_ieee_10k/gcc10 9.80GB/s ± 1% 10.03GB/s ± 1% +2.35% (p=0.000 n=9+10)
wuffs_crc32_ieee_100k/gcc10 13.1GB/s ± 0% 12.9GB/s ± 0% -1.52% (p=0.000 n=10+9)
mimic_crc32_ieee_10k 842MB/s ± 1% 12952MB/s ± 0% +1437.67% (p=0.000 n=10+9)
mimic_crc32_ieee_100k 838MB/s ± 2% 13363MB/s ± 1% +1493.79% (p=0.000 n=10+9)
wuffs_deflate_decode_1k_full_init/clang9 101MB/s ± 0% 106MB/s ± 1% +4.22% (p=0.000 n=8+10)
wuffs_deflate_decode_1k_part_init/clang9 119MB/s ± 1% 121MB/s ± 1% +1.39% (p=0.000 n=10+10)
wuffs_deflate_decode_10k_full_init/clang9 222MB/s ± 0% 215MB/s ± 0% -3.24% (p=0.000 n=9+9)
wuffs_deflate_decode_10k_part_init/clang9 228MB/s ± 0% 218MB/s ± 3% -4.47% (p=0.000 n=10+9)
wuffs_deflate_decode_100k_just_one_read/clang9 291MB/s ± 0% 286MB/s ± 3% -1.85% (p=0.000 n=10+10)
wuffs_deflate_decode_100k_many_big_reads/clang9 189MB/s ± 1% 178MB/s ± 1% -5.50% (p=0.000 n=10+10)
wuffs_deflate_decode_1k_full_init/gcc10 99.1MB/s ± 2% 102.1MB/s ± 1% +3.12% (p=0.000 n=10+9)
wuffs_deflate_decode_1k_part_init/gcc10 117MB/s ± 1% 121MB/s ± 1% +3.41% (p=0.000 n=10+9)
wuffs_deflate_decode_10k_full_init/gcc10 215MB/s ± 1% 218MB/s ± 1% +1.55% (p=0.000 n=10+10)
wuffs_deflate_decode_10k_part_init/gcc10 220MB/s ± 1% 225MB/s ± 0% +2.08% (p=0.000 n=10+8)
wuffs_deflate_decode_100k_just_one_read/gcc10 281MB/s ± 1% 279MB/s ± 1% ~ (p=0.105 n=10+10)
wuffs_deflate_decode_100k_many_big_reads/gcc10 182MB/s ± 1% 180MB/s ± 0% -1.14% (p=0.000 n=9+7)
mimic_deflate_decode_1k_full_init 138MB/s ± 1% 179MB/s ± 1% +29.56% (p=0.000 n=10+10)
mimic_deflate_decode_10k_full_init 155MB/s ± 2% 268MB/s ± 1% +72.15% (p=0.000 n=9+10)
mimic_deflate_decode_100k_just_one_read 191MB/s ± 0% 269MB/s ± 1% +40.38% (p=0.000 n=10+10)
mimic_deflate_decode_100k_many_big_reads 147MB/s ± 1% skipped
wuffs_gzip_decode_10k/clang9 218MB/s ± 1% 211MB/s ± 1% -3.18% (p=0.000 n=8+9)
wuffs_gzip_decode_100k/clang9 282MB/s ± 0% 282MB/s ± 0% ~ (p=0.113 n=9+9)
wuffs_gzip_decode_10k/gcc10 215MB/s ± 1% 231MB/s ± 1% +7.34% (p=0.000 n=10+10)
wuffs_gzip_decode_100k/gcc10 271MB/s ± 2% 293MB/s ± 0% +7.84% (p=0.000 n=10+9)
mimic_gzip_decode_10k 132MB/s ± 1% 263MB/s ± 0% +99.23% (p=0.000 n=10+9)
mimic_gzip_decode_100k 156MB/s ± 1% 262MB/s ± 3% +67.93% (p=0.000 n=9+10)
wuffs_zlib_decode_10k/clang9 223MB/s ± 0% 212MB/s ± 1% -5.05% (p=0.000 n=7+10)
wuffs_zlib_decode_100k/clang9 280MB/s ± 0% 280MB/s ± 0% ~ (p=0.867 n=8+7)
wuffs_zlib_decode_10k/gcc10 232MB/s ± 2% 220MB/s ± 1% -5.42% (p=0.000 n=10+10)
wuffs_zlib_decode_100k/gcc10 286MB/s ± 5% 277MB/s ± 0% -2.88% (p=0.002 n=10+9)
mimic_zlib_decode_10k 145MB/s ± 0% 266MB/s ± 0% +84.02% (p=0.000 n=10+9)
mimic_zlib_decode_100k 173MB/s ± 1% 265MB/s ± 2% +53.31% (p=0.000 n=10+9)
diff --git a/test/c/mimiclib/deflate-gzip-zlib.c b/test/c/mimiclib/deflate-gzip-zlib.c
index 21befbe..a24374b 100644
--- a/test/c/mimiclib/deflate-gzip-zlib.c
+++ b/test/c/mimiclib/deflate-gzip-zlib.c
@@ -14,12 +14,171 @@
// ----------------
-// Uncomment this line to test and bench miniz instead of zlib-the-library.
+// Uncomment one of these #define lines to test and bench alternative mimic
+// libraries (libdeflate or miniz) instead of zlib-the-library.
+//
+// These are collectively referred to as
+// WUFFS_MIMICLIB_USE_XXX_INSTEAD_OF_ZLIB.
+//
+// #define WUFFS_MIMICLIB_USE_LIBDEFLATE_INSTEAD_OF_ZLIB 1
// #define WUFFS_MIMICLIB_USE_MINIZ_INSTEAD_OF_ZLIB 1
-#ifdef WUFFS_MIMICLIB_USE_MINIZ_INSTEAD_OF_ZLIB
+// -------------------------------- WUFFS_MIMICLIB_USE_XXX_INSTEAD_OF_ZLIB
+#if defined(WUFFS_MIMICLIB_USE_LIBDEFLATE_INSTEAD_OF_ZLIB)
+#include "libdeflate.h"
+
+#define WUFFS_MIMICLIB_DEFLATE_DOES_NOT_SUPPORT_STREAMING 1
+
+#define WUFFS_MIMICLIB_ZLIB_DOES_NOT_SUPPORT_DICTIONARIES 1
+
+uint32_t global_mimiclib_deflate_unused_u32;
+
+typedef enum libdeflate_result (*libdeflate_decompress_func)(
+ struct libdeflate_decompressor* decompressor,
+ const void* in,
+ size_t in_nbytes,
+ void* out,
+ size_t out_nbytes_avail,
+ size_t* actual_in_nbytes_ret,
+ size_t* actual_out_nbytes_ret);
+
+const char* //
+libdeflate_result_as_const_char_star(enum libdeflate_result r) {
+ switch (r) {
+ case LIBDEFLATE_SUCCESS:
+ return NULL;
+ case LIBDEFLATE_BAD_DATA:
+ return "libdeflate: bad data";
+ case LIBDEFLATE_SHORT_OUTPUT:
+ return "libdeflate: short output";
+ case LIBDEFLATE_INSUFFICIENT_SPACE:
+ return "libdeflate: insufficient space";
+ }
+ return "libdeflate: unknown error";
+}
+
+const char* //
+mimic_bench_adler32(wuffs_base__io_buffer* dst,
+ wuffs_base__io_buffer* src,
+ uint32_t wuffs_initialize_flags,
+ uint64_t wlimit,
+ uint64_t rlimit) {
+ global_mimiclib_deflate_unused_u32 = 1;
+ while (src->meta.ri < src->meta.wi) {
+ uint8_t* ptr = src->data.ptr + src->meta.ri;
+ size_t len = src->meta.wi - src->meta.ri;
+ if (len > 0x7FFFFFFF) {
+ return "src length is too large";
+ } else if (len > rlimit) {
+ len = rlimit;
+ }
+ global_mimiclib_deflate_unused_u32 =
+ libdeflate_adler32(global_mimiclib_deflate_unused_u32, ptr, len);
+ src->meta.ri += len;
+ }
+ return NULL;
+}
+
+const char* //
+mimic_bench_crc32_ieee(wuffs_base__io_buffer* dst,
+ wuffs_base__io_buffer* src,
+ uint32_t wuffs_initialize_flags,
+ uint64_t wlimit,
+ uint64_t rlimit) {
+ global_mimiclib_deflate_unused_u32 = 0;
+ while (src->meta.ri < src->meta.wi) {
+ uint8_t* ptr = src->data.ptr + src->meta.ri;
+ size_t len = src->meta.wi - src->meta.ri;
+ if (len > 0x7FFFFFFF) {
+ return "src length is too large";
+ } else if (len > rlimit) {
+ len = rlimit;
+ }
+ global_mimiclib_deflate_unused_u32 =
+ libdeflate_crc32(global_mimiclib_deflate_unused_u32, ptr, len);
+ src->meta.ri += len;
+ }
+ return NULL;
+}
+
+const char* //
+mimic_deflate_gzip_zlib_decode(wuffs_base__io_buffer* dst,
+ wuffs_base__io_buffer* src,
+ uint32_t wuffs_initialize_flags,
+ uint64_t wlimit,
+ uint64_t rlimit,
+ libdeflate_decompress_func func) {
+ struct libdeflate_decompressor* dec = libdeflate_alloc_decompressor();
+ if (!dec) {
+ return "libdeflate: alloc failed";
+ }
+ size_t n_dst = 0;
+ size_t n_src = 0;
+ enum libdeflate_result res =
+ (*func)(dec, wuffs_base__io_buffer__reader_pointer(src),
+ ((size_t)wuffs_base__u64__min(
+ rlimit, wuffs_base__io_buffer__reader_length(src))),
+ wuffs_base__io_buffer__writer_pointer(dst),
+ ((size_t)wuffs_base__u64__min(
+ wlimit, wuffs_base__io_buffer__writer_length(dst))),
+ &n_src, &n_dst);
+ if (res == LIBDEFLATE_SUCCESS) {
+ dst->meta.wi += n_dst;
+ src->meta.ri += n_src;
+ }
+ libdeflate_free_decompressor(dec);
+ return libdeflate_result_as_const_char_star(res);
+}
+
+const char* //
+mimic_deflate_decode(wuffs_base__io_buffer* dst,
+ wuffs_base__io_buffer* src,
+ uint32_t wuffs_initialize_flags,
+ uint64_t wlimit,
+ uint64_t rlimit) {
+ return mimic_deflate_gzip_zlib_decode(dst, src, wuffs_initialize_flags,
+ wlimit, rlimit,
+ &libdeflate_deflate_decompress_ex);
+}
+
+const char* //
+mimic_gzip_decode(wuffs_base__io_buffer* dst,
+ wuffs_base__io_buffer* src,
+ uint32_t wuffs_initialize_flags,
+ uint64_t wlimit,
+ uint64_t rlimit) {
+ return mimic_deflate_gzip_zlib_decode(dst, src, wuffs_initialize_flags,
+ wlimit, rlimit,
+ &libdeflate_gzip_decompress_ex);
+}
+
+const char* //
+mimic_zlib_decode(wuffs_base__io_buffer* dst,
+ wuffs_base__io_buffer* src,
+ uint32_t wuffs_initialize_flags,
+ uint64_t wlimit,
+ uint64_t rlimit) {
+ return mimic_deflate_gzip_zlib_decode(dst, src, wuffs_initialize_flags,
+ wlimit, rlimit,
+ &libdeflate_zlib_decompress_ex);
+}
+
+const char* //
+mimic_zlib_decode_with_dictionary(wuffs_base__io_buffer* dst,
+ wuffs_base__io_buffer* src,
+ wuffs_base__slice_u8 dictionary) {
+ return "libdeflate does not implement zlib dictionaries";
+}
+
+// -------------------------------- WUFFS_MIMICLIB_USE_XXX_INSTEAD_OF_ZLIB
+#elif defined(WUFFS_MIMICLIB_USE_MINIZ_INSTEAD_OF_ZLIB)
#include "/path/to/your/copy/of/github.com/richgel999/miniz/miniz_tinfl.c"
+// We deliberately do not define the
+// WUFFS_MIMICLIB_DEFLATE_DOES_NOT_SUPPORT_STREAMING macro.
+
+#define WUFFS_MIMICLIB_ZLIB_DOES_NOT_SUPPORT_DICTIONARIES 1
+
const char* //
mimic_bench_adler32(wuffs_base__io_buffer* dst,
wuffs_base__io_buffer* src,
@@ -101,9 +260,16 @@
return "miniz does not implement zlib dictionaries";
}
-#else // WUFFS_MIMICLIB_USE_MINIZ_INSTEAD_OF_ZLIB
+// -------------------------------- WUFFS_MIMICLIB_USE_XXX_INSTEAD_OF_ZLIB
+#else
#include "zlib.h"
+// We deliberately do not define the
+// WUFFS_MIMICLIB_DEFLATE_DOES_NOT_SUPPORT_STREAMING macro.
+
+// We deliberately do not define the
+// WUFFS_MIMICLIB_ZLIB_DOES_NOT_SUPPORT_DICTIONARIES macro.
+
uint32_t global_mimiclib_deflate_unused_u32;
const char* //
@@ -299,4 +465,5 @@
UINT64_MAX, zlib_flavor_zlib);
}
-#endif // WUFFS_MIMICLIB_USE_MINIZ_INSTEAD_OF_ZLIB
+#endif
+// -------------------------------- WUFFS_MIMICLIB_USE_XXX_INSTEAD_OF_ZLIB
diff --git a/test/c/std/adler32.c b/test/c/std/adler32.c
index 524ebbf..f4fcd10 100644
--- a/test/c/std/adler32.c
+++ b/test/c/std/adler32.c
@@ -37,7 +37,7 @@
"wuffs mimic cflags" to run the mimic benchmarks.
*/
-// ¿ wuffs mimic cflags: -DWUFFS_MIMIC -lz
+// ¿ wuffs mimic cflags: -DWUFFS_MIMIC -ldeflate -lz
// Wuffs ships as a "single file C library" or "header file library" as per
// https://github.com/nothings/stb/blob/master/docs/stb_howto.txt
diff --git a/test/c/std/crc32.c b/test/c/std/crc32.c
index 72b3c21..87560fb 100644
--- a/test/c/std/crc32.c
+++ b/test/c/std/crc32.c
@@ -37,7 +37,7 @@
"wuffs mimic cflags" to run the mimic benchmarks.
*/
-// ¿ wuffs mimic cflags: -DWUFFS_MIMIC -lz
+// ¿ wuffs mimic cflags: -DWUFFS_MIMIC -ldeflate -lz
// Wuffs ships as a "single file C library" or "header file library" as per
// https://github.com/nothings/stb/blob/master/docs/stb_howto.txt
diff --git a/test/c/std/deflate.c b/test/c/std/deflate.c
index b531112..bf0d086 100644
--- a/test/c/std/deflate.c
+++ b/test/c/std/deflate.c
@@ -37,7 +37,7 @@
"wuffs mimic cflags" to run the mimic benchmarks.
*/
-// ¿ wuffs mimic cflags: -DWUFFS_MIMIC -lz
+// ¿ wuffs mimic cflags: -DWUFFS_MIMIC -ldeflate -lz
// Wuffs ships as a "single file C library" or "header file library" as per
// https://github.com/nothings/stb/blob/master/docs/stb_howto.txt
@@ -749,10 +749,9 @@
const char* have = do_test_io_buffers(mimic_deflate_decode,
&g_deflate_deflate_distance_code_31_gt,
UINT64_MAX, UINT64_MAX);
- const char* want = "inflate failed (data error)";
- if ((have != want) &&
- ((have == NULL) || (want == NULL) || strcmp(have, want))) {
- RETURN_FAIL("have \"%s\", want \"%s\"", have, want);
+ if (!strings_are_equal(have, "inflate failed (data error)") &&
+ !strings_are_equal(have, "libdeflate: bad data")) {
+ RETURN_FAIL("have \"%s\", want \"bad data\" or similar", have);
}
return NULL;
}
@@ -924,7 +923,9 @@
test_mimic_deflate_decode_deflate_huffman_primlen_9,
test_mimic_deflate_decode_midsummer,
test_mimic_deflate_decode_pi_just_one_read,
+#ifndef WUFFS_MIMICLIB_DEFLATE_DOES_NOT_SUPPORT_STREAMING
test_mimic_deflate_decode_pi_many_big_reads,
+#endif
test_mimic_deflate_decode_romeo,
test_mimic_deflate_decode_romeo_fixed,
@@ -947,7 +948,9 @@
bench_mimic_deflate_decode_1k_full_init,
bench_mimic_deflate_decode_10k_full_init,
bench_mimic_deflate_decode_100k_just_one_read,
+#ifndef WUFFS_MIMICLIB_DEFLATE_DOES_NOT_SUPPORT_STREAMING
bench_mimic_deflate_decode_100k_many_big_reads,
+#endif
#endif // WUFFS_MIMIC
diff --git a/test/c/std/gzip.c b/test/c/std/gzip.c
index 358126e..e5780a7 100644
--- a/test/c/std/gzip.c
+++ b/test/c/std/gzip.c
@@ -37,7 +37,7 @@
"wuffs mimic cflags" to run the mimic benchmarks.
*/
-// ¿ wuffs mimic cflags: -DWUFFS_MIMIC -lz
+// ¿ wuffs mimic cflags: -DWUFFS_MIMIC -ldeflate -lz
// Wuffs ships as a "single file C library" or "header file library" as per
// https://github.com/nothings/stb/blob/master/docs/stb_howto.txt
diff --git a/test/c/std/zlib.c b/test/c/std/zlib.c
index 921b0c4..22c2371 100644
--- a/test/c/std/zlib.c
+++ b/test/c/std/zlib.c
@@ -37,7 +37,7 @@
"wuffs mimic cflags" to run the mimic benchmarks.
*/
-// ¿ wuffs mimic cflags: -DWUFFS_MIMIC -lz
+// ¿ wuffs mimic cflags: -DWUFFS_MIMIC -ldeflate -lz
// Wuffs ships as a "single file C library" or "header file library" as per
// https://github.com/nothings/stb/blob/master/docs/stb_howto.txt
@@ -384,7 +384,9 @@
test_mimic_zlib_decode_midsummer,
test_mimic_zlib_decode_pi,
+#ifndef WUFFS_MIMICLIB_ZLIB_DOES_NOT_SUPPORT_DICTIONARIES
test_mimic_zlib_decode_sheep,
+#endif
#endif // WUFFS_MIMIC
diff --git a/test/c/testlib/testlib.c b/test/c/testlib/testlib.c
index d3a90ea..aca8335 100644
--- a/test/c/testlib/testlib.c
+++ b/test/c/testlib/testlib.c
@@ -819,6 +819,16 @@
return g_fail_msg;
}
+bool //
+strings_are_equal(const char* s, const char* t) {
+ if (s == t) {
+ return true;
+ } else if ((s == NULL) || (t == NULL)) {
+ return false;
+ }
+ return strcmp(s, t) == 0;
+}
+
// throughput_counter is whether to count dst or src bytes, or neither, when
// calculating a benchmark's MB/s throughput number.
//