Docs Benchmarks

Benchmarks

Measured, not promised. The Rust engine (0.5) is faster than SQLite and PostgreSQL at every size measured, 16× faster than SQLite at p50 on 1M events and 36× on 10M.

Summary

  • 16× faster than SQLite at p50 on 1M events (0.107 ms vs 1.75 ms), and 36× on 10M. Against PostgreSQL: 38× and 124×.
  • Prunes 96.6% of segments at 1M events: a query scores 19 of the 459 events in its window.
  • 8.5x to 19.4x faster than the earlier pure-Python engine, with identical results.
  • Better answers than recency: hit@1 of the true culprit 0.562 vs 0.367 on a simulated week of code changes.

The Rust engine carries most of the speed, and segment pruning adds more as the data grows: brute force over the same Rust store is 1.10x slower at 1M events and 1.54x slower at 10M, while at 10K and 100K events a plain scan is faster.

Query latency

Default kernel (log-normal, median 3h, sigma 0.6), 15 min buckets. Latency in milliseconds.

Nimplp50p95p99mean
10Kheapdb0.0110.0210.0490.012
10Kbruteforce-rust0.0050.0080.0120.005
10Ksqlite-mem0.0250.0430.0640.026
10Kpostgres0.1200.1780.1990.126
100Kheapdb0.0260.0350.0560.028
100Kbruteforce-rust0.0210.0290.0520.022
100Ksqlite-mem0.1870.2690.3470.195
100Kpostgres0.5370.9821.130.621
1Mheapdb0.1070.1670.2000.120
1Mbruteforce-rust0.1190.1570.1730.125
1Msqlite-mem1.752.712.921.85
1Mpostgres4.044.706.204.11
10Mheapdb0.5140.6020.6340.517
10Mbruteforce-rust0.7891.151.210.830
10Msqlite-mem18.529.035.120.2
10Mpostgres63.512917472.0

HeapDB p50 relative to the others (other p50 / heapdb p50; above 1, HeapDB is faster; below 1, slower):

Nheapdb p50 (ms)vs bruteforce-rustvs bruteforcevs sqlite-memvs sqlite-diskvs postgres
10K0.0110.43x0.49x2.28x2.51x11.00x
100K0.0260.81x1.85x7.09x7.05x20.33x
1M0.1071.10x4.12x16.30x16.71x37.58x
10M0.5141.54xnot measured35.93x35.89x123.58x

The Python-loop bruteforce was not measured at 10M: its estimated memory (10.6 GiB) exceeded the VM.

Pruning

Means over the timed queries. Events in window is what brute force scores.

Nevents in windowheapdb events scoredscored p99segments in windowsegments prunedpruned %
1M459.019.230129.2124.796.6%
10M-149.6250133.3129.096.8%

How the pruning works: Core algorithms.

Python engine vs Rust engine

heapdb rows of the v0.4 pure-Python engine re-run on the same CPU, next to the v0.5 Rust engine. Both score exactly the same number of events per query; the gain is the cost per unit of work, not a different algorithm.

NPython p50 msRust p50 msp50 speed-upingest speed-upPython RSS B/eventRust RSS B/event
10K0.0920.0118.5x4.3x2,415808
100K0.3770.02614.3x6.6x2,228607
1M2.080.10719.4x8.3x1,502298
10Mnot measured0.514--not measured178

Where the index pays off and where it doesn't

  • Small N, against brute force. At 10K the window holds 4.6 events and only 13% of segments can be pruned; HeapDB's p50 is 0.011 ms against 0.005 ms for both brute-force implementations (0.43x vs bruteforce-rust, 0.49x vs bruteforce). At 100K it is still slower than bruteforce-rust (0.026 vs 0.021 ms, 0.81x).
  • Pruning pays off as the data grows. With the same scoring code, brute force is 1.10x slower at 1M and 1.54x slower at 10M. For top-k over a short window on small data, a scan gets close.
  • Short or uninformative kernels. With a 10-minute exponential kernel HeapDB is slower than bruteforce-rust (0.72x); with a narrow log-normal and with flat links in a 24h window it roughly ties (0.94x, 0.98x). Table below.
  • Memory against SQLite. HeapDB needs 298 B/event at 1M and 178 B/event at 10M; SQLite in memory needs 139 and 140.

Memory (RSS delta):

Nimplingest events/sRSS delta MiB
1Mheapdb357,197284 (298 B/event)
1Msqlite-mem185,164132 (139 B/event)
10Mheapdb293,9501,701 (178 B/event)
10Msqlite-mem173,4991,331 (140 B/event)

Kernels at 1M events (latency in ms):

kernelheapdb scoredpruned %heapdb p50bruteforce-rust p50bruteforce-rust / heapdb
exp_10m9.463.8%0.0150.0110.72x
lognormal_narrow18.489.1%0.0410.0390.94x
window_24h, flat links117.970.6%0.0730.0720.98x

Ranking quality

hit@1 of the true culprit on a simulated week of code changes (20 seeds), identical for both engines:

methoddays 0-3.5days 3.5-7all
recency0.335 ± 0.0970.411 ± 0.1170.367 ± 0.070
heapdb_proportional0.536 ± 0.0980.600 ± 0.1110.562 ± 0.076

Before any feedback, the kernel, dose and noisy-OR over feature sets take whole-week hit@1 from 0.367 (recency) to 0.536 (priors only); revert feedback raises it to 0.562.

Methodology

We implemented the same ranking problem (top-5 causes of one effect for one entity) six ways and checked that all six return identical answers before timing them: HeapDB, brute force with the same Rust scoring code (bruteforce-rust), a Python brute-force loop over the Rust score function (bruteforce), SQLite in memory and on disk, and PostgreSQL. Every latency includes the Python call.

One 2-vCPU VM (Intel Xeon @ 2.80GHz, 7.8 GiB RAM), Python 3.13, heapdb 0.5.0, SQLite 3.45.1, PostgreSQL 16. Single-threaded, synthetic data with uniform event times; real logs are bursty, which changes pruning. HeapDB ran in-process; SQLite on disk and PostgreSQL were queried warm. Differences of 10% or less between implementations should be treated as ties (run-to-run noise). Read the "Reading these results" section of RESULTS.md before quoting any number. What comes next is on the roadmap.