hdr#
A pure-OCaml High Dynamic Range histogram, after Gil
Tene's HdrHistogram. It records values spread across a wide range -- latencies
from nanoseconds to seconds, say -- at a fixed relative precision, in constant
time and bounded memory, and reports percentiles (p50/p99/p999), min, max, mean
and standard deviation. It records int values; Hdr.Float is the same over
float (HdrHistogram's DoubleHistogram).
It is the structure for honest tail-latency reporting: unlike a naive min/avg/max or a fixed-bucket histogram, it keeps enough resolution at every magnitude to answer "what was the 99.9th percentile?" without storing every sample.
This is a local quantile structure -- you compute the percentile yourself. It
is not a backend for a Prometheus client: a Prometheus histogram exposes
fixed le buckets and quantiles are computed server-side, and a Prometheus
summary wants a targeted-quantile sketch (CKMS) over arbitrary floats. hdr is
for benches, throughput harnesses, the perf-profiling loop, and /debug-style
endpoints.
let h = Hdr.v () (* auto-resizing; record latencies in ns *)
let () = List.iter (Hdr.record h) [ 1_200; 3_400; 900; 12_000 ]
let () = Format.printf "%a@." Hdr.pp h
let () = Format.printf "p99 = %d ns@." (Hdr.value_at_percentile h 99.)
Installation#
Install with opam:
$ opam install hdr
If opam cannot find the package, it may not yet be released in the public
opam-repository. Add the overlay repository, then install it:
$ opam repo add samoht https://tangled.org/gazagnaire.org/opam-overlay.git
$ opam update
$ opam install hdr
Coordinated omission#
When load is offered at a fixed rate, a stalled response also delays the next
measurement, so a closed-loop recorder under-reports the tail. record_corrected ~expected_interval synthesises the samples that a stalled loop would have
missed, the same correction wrk2 and HdrHistogram apply:
let () = Hdr.record_corrected h 50_000 ~expected_interval:10_000
API#
v ?significant_figures ?highest () |
new histogram (default 3 sig figs = 0.1% error); omit highest to auto-resize |
record / record_n / record_corrected |
add a value (allocation-free unless a resize triggers) |
value_at_percentile / percentiles |
quantiles |
count / min / max / mean / stddev |
summary statistics |
add |
merge another histogram in |
iter |
fold over the non-empty buckets |
reset |
clear |
pp |
one-line p50/p90/p99/p999/max summary |
Hdr.Float |
the same API over float values (HdrHistogram's DoubleHistogram) |