perf: single-pass hdr_value_at_percentiles (flat scan, +599%) - #140
fcostaoliveira wants to merge 3 commits into
Conversation
…% (PR #140) hdr_value_at_percentiles: flat counts[] scan (offset==0) replacing the per-bucket iterator; offset-aware iterator fallback kept for decoded histograms. gnr1 same-session A/B: 12,357 -> 86,403 calls/sec (+599%, 7x; 80.9->11.6us). ctest/ASan/nolog green, batch==singular byte-identical, MSVC-safe. Based off official upstream/main (18c7a32), independent of #138/#139. PR HdrHistogram/HdrHistogram_c#140. Logged EXPERIMENTS/SUMMARY/RACE/README/memory.
|
|
7c8af3d to
18ab4ee
Compare
|
Added a regression test ( |
hdr_value_at_percentiles resolved percentiles via a per-bucket hdr_iter_next walk. When normalizing_index_offset == 0 (the common case), replace it with one tight prefix-sum scan over the flat counts[] array (index->value conversion only at crossings). Decoded/rotated histograms (offset != 0) keep the offset-aware iterator path. Percentiles must be ascending, as before; results are byte-identical. Adds a regression test (test_value_at_percentiles_with_offset) that drives a rotated histogram with normalizing_index_offset != 0 and asserts identical percentiles to the unrotated one, so CI covers the offset-aware fallback.
18ab4ee to
40f14fa
Compare
|
🤖 Automated first-pass review — a human maintainer's review is still required before merge. The rewrite looks behaviour-preserving to me: with The one thing worth raising isn't in this diff. Minor: that's now three hand-written prefix-sum scans over The test itself reads fine — poking the fields directly is the only way to get a rotated histogram without an encoded payload, and I can't reproduce the benchmark, and CI doesn't measure performance; the per-PR fuzz gate is ASan only (UBSan is the weekly batch job), so your local ASan/UBSan run is what actually covers that. |
Summary
hdr_value_at_percentilesresolved the requested percentiles via a per-buckethdr_iter_nextwalk. When
normalizing_index_offset == 0(the common case), replace that with a single tightprefix-sum scan over the flat
counts[]array — the index→value conversion runs only at thecrossings. Decoded/rotated histograms (
normalizing_index_offset != 0) keep the offset-awareiterator path, so behavior is unchanged there.
Percentiles must be ascending (unchanged contract); results are byte-identical.
Benchmark
Getting all 7 of {50,75,90,95,99,99.9,99.99} in one
hdr_value_at_percentilescall, single core(Intel Granite Rapids), same-session A/B on an identical workload (
hdr_init(1, 3.6e9, 3), 1MFibonacci-spread values):
+599% (7×).
hdr_record_valueand singularhdr_value_at_percentileare unchanged (controls flat).Correctness
ctestgreen; ASan + UBSan clean.7 percentiles, unchanged).
normalizing_index_offset == 0case uses the directcounts[]scan; decoded histograms still go through the normalizing iterator.HDR_LOG_REQUIRED=DISABLEDbuilds; no intrinsics (MSVC unaffected).