Benchmark Lab
The SketchLog Benchmark Lab measures the core sketch primitives under reproducible, deterministic conditions so infrastructure teams can validate compression, accuracy, and throughput claims on their own hardware.
Quick start
# Run all scenarios and write machine-readable results
PYTHONPATH=python python -m sketchlog.bench_lab \
--output results.json \
--report report.md
# Run a specific subset
PYTHONPATH=python python -m sketchlog.bench_lab \
--scenarios latency_ingest latency_quantile canary_comparison \
--output results.json
Or via the installed entry point:
CLI reference
| Flag | Type | Default | Description |
|---|---|---|---|
--scenarios |
SCENARIO … |
all |
One or more scenario names, or all |
--output |
FILE |
— | Write JSON results to FILE |
--report |
FILE |
— | Write Markdown report to FILE |
--quiet |
flag | off | Suppress per-scenario progress lines |
Exit code is 0 when all scenarios pass, 1 when any scenario fails.
Scenarios
| Name | What it measures |
|---|---|
latency_ingest |
DDSketch.add_batch() throughput and memory over 100 K lognormal samples |
latency_quantile |
DDSketch.quantile() latency and relative accuracy at p50–p99.9 |
latency_merge |
Merge throughput: 16 DDSketch shards combined into one |
unique_ingest |
HyperLogLog.add() throughput and memory over 50 K distinct integers |
unique_accuracy |
HyperLogLog cardinality error across five magnitudes (100 → 50 K) |
freq_ingest |
CountMinSketch.add() throughput and memory over 100 K events |
freq_accuracy |
Non-undercount invariant: estimate(key) >= true_count for all keys |
serialized_size |
Sketch bytes vs raw event bytes, compression ratio for all three types |
canary_comparison |
Detect a simulated 2× latency regression via DDSketch p99 comparison |
All scenarios use a fixed random seed (0xDEADBEEF) so results are
reproducible across runs on the same hardware.
JSON output schema
{
"schema_version": "1",
"generated_at": "2026-07-06T10:00:00Z",
"environment": {
"os": "Linux",
"os_release": "5.15.0",
"machine": "x86_64",
"python": "3.12.3",
"processor": "Intel(R) Xeon(R)"
},
"passed": 9,
"failed": 0,
"scenarios": [
{
"name": "latency_ingest",
"passed": true,
"metrics": {
"n_events": 100000,
"mean_s": 0.043,
"median_s": 0.042,
"stddev_s": 0.001,
"p95_s": 0.045,
"throughput_eps": 2325000,
"memory_bytes": 2512,
"bins_positive": 149,
"bins_negative": 0
},
"notes": ["DDSketch.add_batch(100,000) lognormal latencies, relative_accuracy=0.01"]
}
]
}
Worked example — interpreting latency results
latency_ingest
throughput_eps : 2,325,000 events/sec ingested by DDSketch.add_batch()
memory_bytes : 2,512 bytes for 100 K lognormal events at α=0.01
latency_quantile
max_relative_error : 0.0038 well within the 1 % α guarantee
query_latency_mean : 1.2 µs per full p50/p75/p90/p95/p99/p99.9 sweep
serialized_size (ddsketch)
raw_bytes : 25,600,000 100 K × 256 B raw events
sketch_bytes : 2,512 compact JSON
compression_ratio: 10,191×
canary_comparison
baseline_p99_ms : 14.3 ms
canary_p99_ms : 28.7 ms
regression_ratio : 2.007 2× regression successfully detected
Accuracy guarantees
| Sketch | Metric | Guarantee |
|---|---|---|
DDSketch α=0.01 |
Relative quantile error | ≤ 1 % per quantile |
HyperLogLog precision=12 |
Cardinality relative error | ≤ 5 % (typical < 1 %) |
CountMinSketch w=2048, d=5 |
Frequency estimate | ≥ true count (never undercounts) |
Reproducing locally
# Clone and install
git clone https://github.com/SBALAVIGNESH123/sketchlog
cd sketchlog
pip install -e ".[test]"
# Run full lab
PYTHONPATH=python python -m sketchlog.bench_lab \
--output results.json --report report.md
# Run only accuracy scenarios
PYTHONPATH=python python -m sketchlog.bench_lab \
--scenarios latency_quantile unique_accuracy freq_accuracy
# Run tests
PYTHONPATH=python python -m pytest tests/test_bench_lab.py -q
Caveats
- Warm-up — each scenario runs
_WARMUP=2discard iterations before measuring. Cold-start numbers will differ. - Wall-clock timing — results include Python interpreter and GC overhead. Relative comparisons across runs on the same host are more meaningful than absolute cross-machine comparisons.
- Synthetic workload — latency values are lognormal (mean ~5 ms). Real workloads with heavy tails, bimodal distributions, or near-zero values may produce different bucket counts and memory footprints.
- Serialization proxy —
serialized_sizeuses compact JSON as a wire-size proxy. A binary codec (e.g. MessagePack) would reduce byte counts further. - Single-threaded — all scenarios run single-threaded. Concurrent ingest
throughput is exercised separately in
tests/test_load.py. - Fixed seed — reproducibility is guaranteed only for a given Python version and platform. Cross-platform RNG output may differ for floating-point edge cases.