Expand description
Snapshot-friendly tracing harness for the optimizer and executor.
§What this records
trace_op runs a closure with a thread-local recorder installed. While the recorder is
active, calls to the trace_op! macro inside the optimizer and executor push
structured events into the recorder. The recorder produces a TraceDisplay that renders
as a deterministic, hierarchical text trace suitable for insta snapshot assertions.
Events cover:
- Optimization: optimize/recursive-optimize entry, fixpoint loop iterations, applied reduce rules, applied parent-reduce rules.
- Execution:
execute_untiliterations, single-step entries, parent kernel attempts and matches, slot transitions, builder start/append/finish, and the eventual canonical output.
Despite the name trace_op, the harness is not a generic logging facility: it is closely
coupled to the optimizer/executor state machines so that the resulting trace is stable enough
to commit as a snapshot.
§When to use it
Use trace_op to write a regression test that asserts on the sequence of optimizer
rewrites or executor steps an array goes through. Typical scenarios:
- A reduce rule should fire exactly once on a specific input shape.
- A parent kernel should be tried in a specific order and the first match should win.
- The executor should walk into a slot, finish it, and pop back to the parent without building a canonical intermediate.
- A chunked array should drive the builder path rather than the stack path.
Two resolutions are available:
TraceResolution::ExecutedOnly(default) — only events that actually fired (rule rewrites that matched, kernels that succeeded, execution steps that ran). Optimizer passes that produced no change are elided.TraceResolution::Attempts— also records declined rule attempts, kernels that did not match, and per-loop bookkeeping. Use this when ordering or fall-through matters.
§Cost and scope
- Capture is thread-local. Worker threads spawned inside
fdo not inherit the recorder. - Nested captures return an error so that unrelated traces never merge.
- In release builds and CodSpeed benchmark builds, every
trace_op!invocation is compiled away by the macro’scfggating; this module is then unused. Seetrace_op!for the gating rules.
§Example
use vortex_array::test_harness::trace::trace_op;
let traced = trace_op(|| filter_array.optimize())?;
assert!(traced.output.is::<Primitive>());
insta::assert_snapshot!(traced.trace.to_string(), @r"
optimize root=vortex.filter(i32, len=4) session=false
reduce TrivialFilterRule: vortex.filter(i32, len=4) -> vortex.primitive(i32, len=4)
done output=vortex.primitive(i32, len=4)
");Structs§
- Trace
Display - A stable, snapshot-friendly trace.
- Trace
Options - Options for
trace_op_with. - Traced
- The result of a traced operation.
Enums§
- Trace
Resolution - Controls how much rule and kernel resolution detail is captured.
Functions§
- trace_
op - Run
fwhile capturing a trace of the optimizer and executor work it performs. - trace_
op_ with - Run
fwhile capturing a trace usingoptions.