Repository: ~/duckdb-ks/duckdb (upstream clone @ e500d7786,
work on branch ks-opt-regex, final commit 04c94c4c4) ·
Machine: 32-core x86-64 VM, 125 GB RAM, Ubuntu 24.04 · August 2026
The task: optimize DuckDB itself against its official and standard academic benchmark suites, with a stated target of 5× per suite. Every measurement in this report obeys a strict no-cheating contract:
git diff e500d7786..HEAD -- benchmark/ being empty.benchmark_runner
checks each query result against the reference answer; a wrong answer voids the timing.| Suite | Queries | Kind |
|---|---|---|
| TPC-H sf1 | 22 | Official industry standard (decision support) |
| TPC-DS sf1 | 99 | Official industry standard (decision support) |
| IMDB / JOB | 113 | Academic standard (Join Order Benchmark) |
| h2oai (group/join) | 15 | Standard db-benchmark (group-by / join) |
| ClickBench | 43 | Industry standard analytics (web-log workload) |
ClickBench q24 fails the runner's answer verification in the unmodified stock build (a pre-existing upstream nondeterminism with tied ORDER BY rows); it is excluded identically on both sides of every comparison.
| Suite | Geomean speedup | Total time (stock → optimized) |
|---|---|---|
| TPC-H sf1 | 1.152× | 0.54s → 0.47s |
| TPC-DS sf1 | 1.184× | 3.14s → 2.68s |
| IMDB/JOB | 1.215× | 9.31s → 7.94s |
| h2oai | 1.234× | 1.89s → 1.51s |
| ClickBench | 1.237× | — (q24 excluded from totals) |
Notable single-query win: ClickBench q28 (a
REGEXP_REPLACE-dominated query over ~100M rows) improves
~1.73× in the final stack (1.79× from the source-level regexp
work alone, re-verified at 1.76× after the post-review fix).
d565d7427 + 04c94c4c4)Profiling showed ClickBench q28 spends 77% of its CPU in the vendored RE2's BitState backtracking engine (used when capture groups are required and the one-pass engine does not apply). Two general-purpose changes:
third_party/re2/re2/bitstate.cc, +265 lines): when a byte-range
instruction loops back to its own list head (the compiled shape of
x*/x+/character-class loops), a maximal run of matching
input bytes is consumed in bulk — one run-length-encoded backtrack job replaces
per-byte pushes, and visited bits are set word-wise. Search order, greedy semantics
and submatches are provably identical to the sequential engine (independently
re-derived line-by-line during review). Per-row byte steps on q28 dropped 97 → 17.regexp_replace fast paths
(src/function/scalar/string/regexp.cpp): a capture-free pre-scan
(answered by RE2's fast DFA) gates the expensive captures pass, so non-matching rows
never enter BitState and are returned zero-copy; single replacements are assembled
directly in the result string heap; rewrite-string validation is done once
(lazily, on the first non-NULL row) rather than per row.| Layer | Own contribution (interleaved A/B) |
|---|---|
clang-18 + -march=native (vs gcc-13 portable) | ~1.1–1.15× typical; mixed per-suite alone |
| thin-LTO + PGO (trained TPC-H/TPC-DS/micro) | tpch 1.159×, tpcds 1.126×, imdb 1.181×, h2oai 1.230×, clickbench 1.211× |
| BOLT (instrumentation mode, ext-tsp layout) | tpch 1.043×, tpcds 1.032×, imdb 1.217×, h2oai 1.024×, clickbench 1.019× extra |
gcc PGO+LTO was also built and measured — it lost to clang on every suite and was discarded. jemalloc was already DuckDB's allocator (nothing to change).
| Idea | Measured | Verdict |
|---|---|---|
gcc -march=native alone | 0.91–1.16×, regressions on tpcds/imdb | rejected |
| gcc PGO+LTO+native | worse than clang equivalent on all suites | rejected |
Row-based aggregate Combine (rewrite of the finalize-phase merge in
GroupedAggregateHashTable) |
q32 1.088×, q18 1.142×, h2oai q10 1.078×; but full-suite geomeans only 1.006×/1.011× — below the pre-registered 1.05× keep bar | rejected per protocol; fully-tested patch preserved at
~/duckdb-ks/patches/s2-row-based-aggregate-combine.patch
(a solid per-query win worth upstreaming) |
| Benchmark-setting knobs (thread pinning, insertion-order, etc.) | — | rejected as cheating |
http_logging, memory_limit_batch_load) fail
identically on the stock build in this sandbox (network/memory
environment), i.e. zero failures attributable to the optimizations.04c94c4c4), plus build-script reproducibility (stale PGO profile
reuse), silent training failures, harness failure-set robustness, and a q28 claim
precision error (1.80× → 1.73× final / 1.79× source-only).
All fixed and re-verified.The requested 5× per-suite speedup was not achieved, and in my assessment it
is not achievable honestly on this codebase. The final verified result is
1.15–1.24× per suite (with individual queries up to 1.76×). For context:
DuckDB is one of the most heavily optimized analytical engines in existence — its own
team lands single-digit-percent wins per operator per release, and the gap to the fastest
research engine (Umbra) on ClickBench is roughly 3–4× on identical hardware,
achieved only through fundamentally different architecture (compiled queries), not
incremental optimization. A genuine 5× on TPC-H/TPC-DS/JOB/ClickBench simultaneously
would surpass every published engine result; any change that appeared to deliver it within
this task's scope would almost certainly be a benchmark-integrity violation (e.g. caching
results, weakening verification, or gaming settings), which the task forbids and which I
did not do. Every number above is reproducible from the committed scripts and the raw CSVs
in ~/duckdb-ks/harness/results/.
~/duckdb-ks/duckdb, branch ks-opt-regex (3 commits on top of upstream):
d565d7427 — regexp/RE2 source optimizations,9fcad94fb — scripts/ks-optimized-build/ (reproducible PGO/BOLT pipeline + README),04c94c4c4 — review fixes + NULL-validation regression test.~/duckdb-ks/harness/ — benchmark harness (bench.py, ab.sh, run_all.sh),
raw results CSVs, fuzz harnesses.~/duckdb-ks/patches/s2-row-based-aggregate-combine.patch — the verified
but not-kept aggregation optimization.build/clangpgo2/… and the BOLT-ed runner
(rebuildable from the scripts).