summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Moinvaziri <nathan@nathanm.com>2026-02-26 16:10:11 -0800
committerHans Kristian Rosbach <hk-github@circlestorm.org>2026-03-09 23:56:37 +0100
commit006166b5c451cae55fca312c1866cb022ce5ce0c (patch)
treeab81df1d2516f44536e580aa4b129053137469bb
parent9944c1fcf195450f86fd83d974246ec75e466802 (diff)
downloadProject-Tick-006166b5c451cae55fca312c1866cb022ce5ce0c.tar.gz
Project-Tick-006166b5c451cae55fca312c1866cb022ce5ce0c.zip
Add parameterized deflate benchmark
Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
-rw-r--r--test/benchmarks/CMakeLists.txt1
-rw-r--r--test/benchmarks/benchmark_deflate.cc147
2 files changed, 148 insertions, 0 deletions
diff --git a/test/benchmarks/CMakeLists.txt b/test/benchmarks/CMakeLists.txt
index acd320d3c6..df6f5a7e69 100644
--- a/test/benchmarks/CMakeLists.txt
+++ b/test/benchmarks/CMakeLists.txt
@@ -50,6 +50,7 @@ set(BENCH_INTERNAL_SRCS
benchmark_compare256_rle.cc
benchmark_crc32.cc
benchmark_crc32_copy.cc
+ benchmark_deflate.cc
benchmark_insert_string.cc
benchmark_slidehash.cc
)
diff --git a/test/benchmarks/benchmark_deflate.cc b/test/benchmarks/benchmark_deflate.cc
new file mode 100644
index 0000000000..625ccd8eca
--- /dev/null
+++ b/test/benchmarks/benchmark_deflate.cc
@@ -0,0 +1,147 @@
+/* benchmark_deflate.cc -- benchmark deflate() with various levels and raw mode
+ * Copyright (C) 2026 Nathan Moinvaziri
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include <stdio.h>
+#include <assert.h>
+#include <benchmark/benchmark.h>
+
+extern "C" {
+# include "zbuild.h"
+# include "zutil_p.h"
+# if defined(ZLIB_COMPAT)
+# include "zlib.h"
+# else
+# include "zlib-ng.h"
+# endif
+# include "compressible_data_p.h"
+}
+
+#define MAX_SIZE (1024 * 1024)
+
+/* Parameterized deflate benchmark: Args(size, level) */
+class deflate_bench: public benchmark::Fixture {
+private:
+ uint8_t *inbuff = nullptr;
+ uint8_t *outbuff = nullptr;
+ z_uintmax_t outbuff_size = 0;
+
+public:
+ void SetUp(::benchmark::State& state) {
+ outbuff_size = PREFIX(deflateBound)(NULL, MAX_SIZE);
+ outbuff = (uint8_t *)malloc(outbuff_size);
+ if (outbuff == NULL) {
+ state.SkipWithError("malloc failed");
+ return;
+ }
+
+ inbuff = gen_compressible_data(MAX_SIZE);
+ if (inbuff == NULL) {
+ free(outbuff);
+ outbuff = NULL;
+ state.SkipWithError("gen_compressible_data() failed");
+ return;
+ }
+ }
+
+ void Bench(benchmark::State& state, int window_bits, int strategy = Z_DEFAULT_STRATEGY) {
+ int err;
+ size_t size = (size_t)state.range(0);
+ int level = (int)state.range(1);
+
+ PREFIX3(stream) strm;
+ strm.zalloc = NULL;
+ strm.zfree = NULL;
+ strm.opaque = NULL;
+ strm.total_in = 0;
+ strm.total_out = 0;
+ strm.next_out = NULL;
+ strm.avail_out = 0;
+
+ err = PREFIX(deflateInit2)(&strm, level, Z_DEFLATED, window_bits, MAX_MEM_LEVEL, strategy);
+ if (err != Z_OK) {
+ state.SkipWithError("deflateInit2 did not return Z_OK");
+ return;
+ }
+
+ for (auto _ : state) {
+ err = PREFIX(deflateReset)(&strm);
+ if (err != Z_OK) {
+ state.SkipWithError("deflateReset did not return Z_OK");
+ PREFIX(deflateEnd)(&strm);
+ return;
+ }
+
+ strm.avail_in = (uint32_t)size;
+ strm.next_in = (z_const uint8_t *)inbuff;
+ strm.next_out = outbuff;
+ strm.avail_out = (uint32_t)outbuff_size;
+
+ err = PREFIX(deflate)(&strm, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ state.SkipWithError("deflate did not return Z_STREAM_END");
+ PREFIX(deflateEnd)(&strm);
+ return;
+ }
+ }
+
+ err = PREFIX(deflateEnd)(&strm);
+ if (err != Z_OK) {
+ state.SkipWithError("deflateEnd did not return Z_OK");
+ return;
+ }
+ }
+
+ void TearDown(const ::benchmark::State&) {
+ free(inbuff);
+ free(outbuff);
+ }
+};
+
+#define BENCHMARK_DEFLATE_ARGS \
+ ->Args({1024, 1})->Args({1024, 3})->Args({1024, 6})->Args({1024, 9}) \
+ ->Args({16384, 1})->Args({16384, 3})->Args({16384, 6})->Args({16384, 9}) \
+ ->Args({131072, 1})->Args({131072, 3})->Args({131072, 6})->Args({131072, 9}) \
+ ->Args({1048576, 1})->Args({1048576, 3})->Args({1048576, 6})->Args({1048576, 9})
+
+/* Parameterized deflate with zlib wrapping (includes adler32 checksum) */
+BENCHMARK_DEFINE_F(deflate_bench, deflate_level)(benchmark::State& state) {
+ Bench(state, MAX_WBITS);
+}
+BENCHMARK_REGISTER_F(deflate_bench, deflate_level) BENCHMARK_DEFLATE_ARGS;
+
+/* Parameterized raw deflate without checksum */
+BENCHMARK_DEFINE_F(deflate_bench, deflate_nocrc)(benchmark::State& state) {
+ Bench(state, -MAX_WBITS);
+}
+BENCHMARK_REGISTER_F(deflate_bench, deflate_nocrc) BENCHMARK_DEFLATE_ARGS;
+
+/* Strategy benchmarks use fewer size/level combos to keep test count reasonable */
+#define BENCHMARK_DEFLATE_STRATEGY_ARGS \
+ ->Args({1024, 1})->Args({1024, 6})->Args({1024, 9}) \
+ ->Args({1048576, 1})->Args({1048576, 6})->Args({1048576, 9})
+
+/* Parameterized deflate with filtered strategy */
+BENCHMARK_DEFINE_F(deflate_bench, deflate_filtered)(benchmark::State& state) {
+ Bench(state, MAX_WBITS, Z_FILTERED);
+}
+BENCHMARK_REGISTER_F(deflate_bench, deflate_filtered) BENCHMARK_DEFLATE_STRATEGY_ARGS;
+
+/* Parameterized deflate with Huffman-only strategy */
+BENCHMARK_DEFINE_F(deflate_bench, deflate_huffman)(benchmark::State& state) {
+ Bench(state, MAX_WBITS, Z_HUFFMAN_ONLY);
+}
+BENCHMARK_REGISTER_F(deflate_bench, deflate_huffman) BENCHMARK_DEFLATE_STRATEGY_ARGS;
+
+/* Parameterized deflate with RLE strategy */
+BENCHMARK_DEFINE_F(deflate_bench, deflate_rle)(benchmark::State& state) {
+ Bench(state, MAX_WBITS, Z_RLE);
+}
+BENCHMARK_REGISTER_F(deflate_bench, deflate_rle) BENCHMARK_DEFLATE_STRATEGY_ARGS;
+
+/* Parameterized deflate with fixed Huffman codes */
+BENCHMARK_DEFINE_F(deflate_bench, deflate_fixed)(benchmark::State& state) {
+ Bench(state, MAX_WBITS, Z_FIXED);
+}
+BENCHMARK_REGISTER_F(deflate_bench, deflate_fixed) BENCHMARK_DEFLATE_STRATEGY_ARGS;