Workflow Profiling v1
September 13, 2026 · View on GitHub
Status: experimental, opt-in benchmark instrumentation.
Audience: compiler contributors and performance operators.
Workflow profiling records bounded timing observations around selected compiler, project, and prepared-interpreter stages. It is a diagnostic aid for local performance investigation. It is not a language feature, a semantic profile, or an authorization mechanism.
Enabling the observer
The unstable-workflow-profiling Cargo feature is deliberately absent from the
default feature set. A normal build therefore contains no active workflow
observer and no profiling overhead at the instrumentation sites. The
workflow_observer benchmark also declares this feature as a required feature;
it must be enabled explicitly when building or running that target.
The feature exposes semaprax::workflow_profile::capture, Observation, and
the closed Stage inventory to the benchmark host. Instrumentation is compiled
at the selected sites only when the feature is enabled. The current stage
inventory is:
parse, canonicalize, resolve, hir_validate, workspace_preflight,
project_link, graph_render, analysis_index, target_admission,
image_derivation, interpreter_preparation, and prepared_execution.
Changing that inventory is a schema change for
benchmark.workflow-observation.v1; consumers fail closed on stage drift.
Observation semantics
capture measures one synchronous operation with std::time::Instant and
stores its session in thread-local state. Observation.total_ns is elapsed wall
time for the whole closure. Each stage reports its call count, inclusive wall
time, and self wall time. Inclusive time includes nested instrumented stages;
self time subtracts nested instrumented time on the same thread. The sum of
self times is therefore useful for the closed instrumentation sites, but it is
not exhaustive CPU attribution.
The observer follows the thread on which capture runs. Work performed by a
worker thread is not traced as a separate interior: when the caller waits for a
worker, that wait is part of the caller's enclosing span. A capture started on a
child thread has an independent thread-local session and does not appear in the
parent's observation. Scheduling, blocking, preemption, and other host effects
remain in the wall-clock values.
Captures cannot be nested. A nested call returns CaptureBusy without running
its closure. The session is cleaned up on unwinding, so a panic does not leave
observation state active for later work. These refusal and unwind paths are
observability behavior; they do not turn a failed operation into a successful
measurement.
Bounds and completeness
The enabled observer accepts at most 64 simultaneously open span frames and
1,000,000 span entries per capture. When either bound is reached, the live
operation continues, but additional spans are omitted and the observation is
marked complete: false. A malformed span drop also marks the observation
incomplete. The benchmark host asserts completeness and the campaign validator
rejects any incomplete sample, so truncated data cannot be summarized as a
normal observation.
The limits are an evidence bound, not a limit on compiler or interpreter
behavior. complete: true means that the bounded observer recorded all spans
that were opened at its instrumented sites for that capture and closed its
stack consistently. It does not mean that all work, all threads, or all CPU
activity was measured.
Product equality and authority boundary
Timing is collected around ordinary operations and does not define their results. The workflow observer compares the products of cold and warm frontend arms, and compares traced and untraced execution outcomes; it also retains a plain uncaptured timing for comparison. Those equality checks are the benchmark fixture's guards against changing the product while observing it. They are not proof that two arbitrary implementations are equivalent.
Observations carry no compiler, validation, execution, filesystem, workspace,
commit, or publication authority. They do not enter canonical source,
canonical formatting, semantic graph JSON, Wasm bytes, diagnostics, project
revisions, execution traces, or other generated artifacts. Recording or
serializing an observation cannot admit a target, authorize a transaction,
change an ACTIVE generation, or promote evidence. The observer is a benchmark
host facility and must not be used as a substitute for the ordinary locks,
checks, or commit boundaries.
Campaign protocol and non-claims
benchmarks/performance-v1/observe-workflows.py launches the already-built
observer independently for each campaign, records the observer binary digest,
source inventory digest, commit, dirty-tree state, profile, host facts, and
configuration, and fails closed on source or binary drift. It requires a quiet
host before and after each campaign, bounds campaigns to 1–5 and samples to
1–20, rejects malformed or incomplete documents, and emits
benchmark.workflow-campaign.v1. A campaign is quiet_observed only after all
requested campaigns pass these checks; nonquiet, failed, and drifted
results are diagnostic evidence and are not successful measurements.
An observation or campaign does not claim:
- a hosted, cross-platform, physical-device, or production result;
- a speedup, regression, capacity limit, or ranking for real deployments;
- stable absolute performance across hosts, kernels, toolchains, profiles, or builds;
- exhaustive CPU, wall-clock, allocation, I/O, or worker-thread attribution;
- that an instrumented timing equals the performance of an uninstrumented release build; or
- that a quiet host removes all scheduler, thermal, cache, or background-work variance.
Use the values to compare like-for-like observations with the recorded subject, fixture, profile, and host metadata. Product equality is a separate invariant from timing equality, and neither one upgrades local benchmark evidence into a semantic, hosted, or production claim.