Skip to content

Suppress span-parent deps for embed-only queries [span-shift serde 25.0B -> 10.9B; -10% plain touch] - #92

Closed
xmakro wants to merge 1 commit into
mainfrom
perf/span-parent-dep-suppression
Closed

Suppress span-parent deps for embed-only queries [span-shift serde 25.0B -> 10.9B; -10% plain touch]#92
xmakro wants to merge 1 commit into
mainfrom
perf/span-parent-dep-suppression

Conversation

@xmakro

@xmakro xmakro commented Aug 4, 2026

Copy link
Copy Markdown
Owner

Split from #88 (integrated stack and cumulative numbers there). Independent of the other pieces.

track_span_parent makes every query that inspects a parented span record a dependency on source_span(parent). That is the right conservative default, but for a small set of queries it only buys wasted re-execution: their results embed spans verbatim, derive nothing from the absolute positions, and every consumer rebases spans on reuse. For those, a position shift in the parent re-runs the query to produce a result that is identical except for the embedded positions.

thir_body is the amplifier that makes this expensive: it is no_hash, so it has no result fingerprint, so any red dependency makes it unconditionally red and drags mir_built and the rest of the MIR chain along.

This adds a TaskDepsRef::AllowIgnoringSpanParents variant, selected per DepKind in DepGraphData::with_task via suppresses_span_parent_deps(), for: thir_body, typeck_root, mir_built, check_unsafety, check_match, region_scope_tree.

Why this is sound:

  • Suppression only affects span reads made directly inside the listed query's own task. Sub-queries record their own dependencies under their own tasks, so a const-eval query called from typeck still tracks source_span normally.
  • Debuginfo stays correct because codegen tracks its own span reads. Verified empirically: a 3-line shift moves DWARF decoded line info by exactly 3.
  • Diagnostics emitted by consumers of these results rebase spans on replay.

Perf: on the serde span-shift microbench (300 structs, one-line insertion at the top, instructions), this drops 24.95B to 10.88B on top of the two hashing fixes from #88, with no unstable flags involved. A plain-code control crate improves 10% on touch rebuilds (0.494B to 0.445B). On the collector (6 crates x check/debug/opt, jemalloc, geomean, on top of the hashing fixes): incr-patched:println goes from -5.39% to -7.13%, incr-full from +0.05% to -0.19%, no cell regressed at or above 0.25%. Not benchmarked fully isolated from the hashing fixes; needs its own perf run.

Validation (as part of the #88 stack): tests/incremental clean, full tests/ui clean (21309 tests), forced -Zincremental-verify-ich across 9 successive span shifts in both flag states with no panics, DWARF line tables verified against a shift, touch scenarios unregressed.

Siblings: #89, #90, #91, #93.

@xmakro

xmakro commented Aug 6, 2026

Copy link
Copy Markdown
Owner Author

Closing after re-measuring on top of #97 + #98. The re-execution this suppressed no longer happens: with the source_span anchors content-addressed (#97) and expansion contexts position-independent (#98), a span shift leaves those dependencies green, so there is nothing left to suppress. Rebased onto #98 and benchmarked (p94_spandep1_j vs p93_expn2_j): incr-patched -0.05%, i.e. the original effect is gone. A small residual remains from recording fewer edges (incr-full -0.25% geomean, 0 regressions), which would be better served by a dedicated dep-graph-size change than by this allowlist. The thir_body observation (no_hash, so a red dependency propagates with no early cutoff) is worth keeping in mind independently.

@xmakro xmakro closed this Aug 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant