Benchmarking¶
cl-weave includes a small, dependency-free micro-benchmarking helper for
observing how long code takes. It is deliberately separate from the assertion
engine: benchmarks report timings for you to read, while stable CI limits belong
in per-test :timeout-ms (see Test Execution) or the
:to-run-under-ms matcher (see Assertions and Matchers).
benchmark and measure¶
benchmark is a macro that times a body with its lexical bindings intact;
measure is the function it expands to, for when you already have a thunk.
(let ((result (cl-weave:benchmark (:warmup 2 :samples 5 :iterations 100)
(reduce #'+ (list 1 2 3 4 5)))))
(cl-weave:mean-ms result))
Both accept the same three options:
:warmup— calls made and discarded before timing, to settle caches and JIT state (default0).:samples— number of timed samples collected (default10).:iterations— calls per sample; each sample is the average elapsed milliseconds of this many calls, which smooths out clock granularity for very fast code (default1).
:warmup must be a non-negative integer; :samples and :iterations must be
positive integers. Invalid values fail fast with a cl-weave error.
Reading the result¶
Both forms return a benchmark-result. Its accessors expose the raw data, and
four helpers summarize the samples:
| Accessor / helper | Meaning |
|---|---|
benchmark-result-samples |
list of per-sample average milliseconds |
benchmark-result-iterations |
calls averaged into each sample |
benchmark-result-warmup |
warmup calls that were discarded |
minimum-ms |
fastest sample |
maximum-ms |
slowest sample |
mean-ms |
arithmetic mean of the samples |
median-ms |
median sample |
(let ((result (cl-weave:benchmark (:samples 20) (compute-report))))
(list :fastest (cl-weave:minimum-ms result)
:median (cl-weave:median-ms result)
:mean (cl-weave:mean-ms result)
:slowest (cl-weave:maximum-ms result)))
When (not) to gate on timings¶
Wall-clock timings vary with machine load, so treating them as CI pass/fail gates makes suites flaky. Use benchmarks to investigate and compare implementations interactively, and keep hard limits deterministic:
- a per-test budget with
:timeout-ms, or - an assertion with
(expect thunk :to-run-under-ms 5)when you truly need a ceiling in the suite.