experiment design
Design goal
A benchmark compares implementations that are supposed to compute the same
thing. experiment states what “the same” means (oracles), makes a failure
small enough to debug (shrinking), and decides when a size-dependent preference
is strong enough to become a deployment rule (crossover analysis). Everything
is a pure function of explicit inputs.
Mathematical background
Oracles as relations
For an input and step , a reference oracle defines an expected outcome and a judgement for the actual outcome . Equality is the special case ; floating-point code usually needs a tolerance , and IEEE-aware code compares flags as well.
A relational oracle judges a pair of implementations, . It does not need a reference, but it only detects disagreement: if all implementations share a bug, the relation holds. The runner checks all unordered pairs of implementations; when the relation is an equivalence (for example exact equality of results), the pairs are redundant but cheap, and a single deviating implementation shows up in pairs, which makes it easy to identify.
Shrinking as greedy descent
Let be the candidates of and the failure predicate. shrink
computes
and stops when no candidate satisfies or after max_steps evaluations of
.
- Termination. Every iteration of the inner loop evaluates once and
increments a counter; the outer loop stops when the counter reaches
max_stepsor an iteration accepts nothing. At mostmax_stepsevaluations happen, even when is cyclic. - Invariant. If holds, then holds for every accepted
, because a candidate is accepted only when holds for it. The result
is therefore still a failing input. (
shrinkdoes not test itself.) - Local minimality. If the loop stops because no candidate fails, the result is a local minimum: no element of satisfies . If it stops because of the budget, it may not be.
With and a threshold predicate , the descent halves while it can and then steps down by one, reaching exactly in accepted steps.
Crossover detection
Let be sorted scales and the verdict at . The number of transitions is
If the relative delta is monotone in the scale, the labels form a monotone sequence (or the reverse), so a well-behaved preference has at most one transition. yields the boundary of the unique transition; means the preference flips more than once and cannot be expressed as one threshold; means no adjacent pair of definite, different labels.
comparator_label(r, t) maps the relative delta to the labels with the same
threshold rule as stats: if , if , Unknown
otherwise. The Unknown band of width keeps noise around from
creating spurious transitions.
Design decisions
Oracles are values
Problem. Each case needs its own notion of correctness. Choice. Oracles are records of functions with an id. Why. They can capture tolerances and contexts, are named in every validation event, and can be built inline.
Outcomes, not just values, reach the oracle
The oracle sees ExecutionOutcomes, so it can accept a documented
ExpectedDifference, compare raised flags, or require that both sides trap.
The runner pre-classifies worker crashes, timeouts, decoding errors and
Unsupported before the oracle is called, so oracles only judge real results.
Greedy, first-improvement shrinking
Options. Exhaustive search for the smallest failing input; delta debugging; greedy descent. Choice. Greedy descent with an explicit candidate function and an evaluation budget. Why. Each evaluation may run a whole operation sequence, so the budget is what bounds the cost; the candidate function lets the user encode the structure of the input (halve a size, drop an element). The accepted path is recorded so a reader can see how the counterexample was reached.
Conservative crossover
Problem. A crossover becomes a deployment rule (DeploymentPolicy::Piecewise)
that will be applied to inputs never measured. Choice. Accept a boundary
only for exactly one transition; report NonMonotonic otherwise and leave the
policy to the user. Why. A rule built from a noisy, flipping preference
would encode noise.
Correctness and invariants
shrinkevaluates the predicate at mostmax_stepstimes and returns an input satisfying it whenever the initial input does.crossover_from_labelsreturnsFoundonly when there is exactly one transition, and its boundary consists of the two adjacent scales of that transition.ReferenceOracle::equalreturnsValidonly for twoValueoutcomes accepted by the comparator.comparator_labelpartitions the real line into , , for .
Alternatives rejected
- Statistical change-point detection on raw timings. Needs a noise model; labels from practical thresholds are explainable.
- Interpolating the boundary. The scales between two measured ones were not measured; the result names the two measured scales instead.
- Delta debugging. Powerful for sequences, but needs a fixed input representation; the candidate function is more general.
Boundaries
crossover_from_labelsdoes not sort the domain and does not useScaleDomain.compare; pass sorted values.- A transition across an
Unknownlabel (A, Unknown, B) is not counted, so such a sequence reportsNoCrossover. - Oracles are not run here; the runner runs them.
ReferenceOracle.sequence_lengthis not used by the runner. shrinkdoes not check that the initial input fails.