Skip to main content

Module trace

Module trace 

Source
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_until iterations, 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 f do 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’s cfg gating; this module is then unused. See trace_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§

TraceDisplay
A stable, snapshot-friendly trace.
TraceOptions
Options for trace_op_with.
Traced
The result of a traced operation.

Enums§

TraceResolution
Controls how much rule and kernel resolution detail is captured.

Functions§

trace_op
Run f while capturing a trace of the optimizer and executor work it performs.
trace_op_with
Run f while capturing a trace using options.