Skip to content

Emitter: variant membership reads the key set the carrier already holds (emit phase 253s -> 135s) - #12558

Closed
briansrls wants to merge 1 commit into
mainfrom
emit-variant-membership-lookup
Closed

briansrls wants to merge 1 commit into
mainfrom
emit-variant-membership-lookup

Conversation

@briansrls

Copy link
Copy Markdown
Contributor

The seed's Rust emitter spent most of its emit phase recomputing a fact it already carries. This is the first of the repairs from a perf profile of that phase.

The defect

v1.compiler.infer_emit_info is_known_variant answers "does any enum in the closure declare this variant spelling?". It did so by scanning map_values(type_summaries) on every call.

But derive_variant_to_enum already builds exactly that key set, from every variant_name_set key of every EnumRepr summary, and every EmitGraphInfo carries the result as variant_to_enum. build_emit_graph_info derives it from the same built.type_summaries, and every other constructor copies the two fields from one base (all eleven .dag constructors were checked).

So each call rebuilt a set its predecessor had already stored. The link broke its own contract, which makes it the earliest unjustified boundary in the chain (DESIGN §6b). The repair is local to it.

Measured. The profile was perf at 199 Hz with frame pointers, attached to the seed for exactly the compile.emit phase of gunbc compile --source-root dag --source-root src/v2 --entry src/v2/compiler/00_compile.dag --target rust. At 5bf2b13fb8e (current main, which already includes #12454), is_known_variant accounted for 48% of emit-phase samples inclusive, mostly under import_module_enum_scope. Rendering (emit_typed_item) was 14%.

Change

  • is_known_variant(variant_to_enum, name) = map_contains_key(variant_to_enum, name). The parameter is the derived map, so a caller can only hand it the key set the carrier built.
  • v1.compiler.emit_rust call sites. The seven call sites read variant_to_enum:
    • emit_specific_import_use_lines binds it once and passes it to is_import_graph_type_name, import_module_enum_scope and import_variant_parent_for_name;
    • reference_derived_use_line_plan and discriminant_zero_field_variant_tag read it from emit_info.
  • reference_derived_candidate_disposition reads variant_to_enum once, for both membership and parent. The old Absent → CandidateVariantParentUnresolved arm was unreachable while membership was a separate scan. Now the shape cannot express it. The function's now-dead type_summaries parameter is removed.
  • v1.tests.claim.reference_derived_disposition_census_witness_test drops that argument, the two fixtures only it used, and their import.
  • gunbc.emit_summary_map_consumer_partition. is_known_variant no longer reads the summary map, so its consumer row is removed. Its guard row stays and is re-worded: the key set is still quantified over every enum summary, so the "answers true more often as the input degrades" finding still holds.
  • gunbc.recurring_failure_mode emit_stage_cost_dominates_its_closure gains the attribution for the v2.compiler.compile closure. It is scoped to that closure; the 547-module specimen's trigger stays open.
  • Mirrors regenerated: v1_compiler_infer_emit_info.rs, v1_compiler_emit_rust.rs, and the census witness mirror.

Controls

Byte identity. Base seed (main) and new seed each emitted 00_compile.dag 3 times, as concurrent pairs, from one fixed snapshot of this commit. All 6 output trees are identical: 214 files, 0 differences, and no base-vs-base flip.

emit phase (s) whole compile (s)
base (5bf2b13fb8e) 249 / 260 / 251 509 / 523 / 530
this PR 142 / 132 / 131 423 / 395 / 408

The profile-based estimate for this change was about 135 s. The stage0 regen round, whose seed emission runs the same predicate, fell from 618 s to 539 s.

control result
regen round 1 (claim_executor --required-regen) drift is exactly the three mirrors of the edited authorities
regen round 2 after install first_generation_equal=true, 161/161
--required-regen-fixed-point fixed_point_equal=true at 3b5fdf6d855
cargo clippy --all-targets -- -D warnings clean; every stage0 partition crate was checked
census witness, run directly (gunbc run --source-root src/v1 --source-root dag --entry src/v1/tests/claim/reference_derived_disposition_census_witness_test.dag --claim-run) the variant-arm rows pass: delegated to E, an ambiguous "" is unresolved, type position goes to the registry, a non-variant is registry-absent. See the finding below for the three failures
tools.seed_growth_change_population main exit 0

Finding, pre-existing and not fixed here. Three rows of that census witness fail identically on main and on this PR: candidate_provided_by_this_module_is_own_module, cross_module_candidate_without_export_proof_is_export_proof_failed and cross_module_candidate_with_export_proof_survives. The pass/fail sets are equal. The cause is that lookup_item_by_leaf now resolves through emit_info.item_leaf_owner_modules, while those fixtures pass empty_emit_graph_info(), so every registry lookup answers ItemNotFound. The file's own note records that no CI step runs it, which is how the rot went unseen.

Not in this PR

These are the next steps from the same derivation, each its own change with the same controls:

This change does not advance the trigger of an_authored_import_emits_no_use_line_when_its_spelling_is_forked. The predicate is still consulted in import planning, just in O(1) now.

Contention. #12448 and #12401 also regenerate v1_compiler_emit_rust.rs. There is no textual overlap in the .dag, but whichever lands second regenerates the mirror.

🤖 Generated with Claude Code

v1.compiler.infer_emit_info is_known_variant rescanned map_values(type_summaries)
on every question, rebuilding the set derive_variant_to_enum already stores on
EmitGraphInfo as variant_to_enum. Its keys are exactly every variant_name_set
key of every EnumRepr summary, and every EmitGraphInfo constructor pairs the
two fields from one base, so membership is map_contains_key(variant_to_enum, n).
In a profile of the v2.compiler.compile emission at 5bf2b13, that rescan
was the largest cost of the emit phase, mostly under import_module_enum_scope.

- is_known_variant takes variant_to_enum, so a caller can only hand it the key
  set the carrier derived. The seven call sites in v1.compiler.emit_rust read
  it; is_import_graph_type_name, import_module_enum_scope and
  import_variant_parent_for_name carry it from emit_specific_import_use_lines.
- reference_derived_candidate_disposition answers membership and parent with
  ONE read of variant_to_enum, and its dead type_summaries parameter goes.
  The arm that was unreachable while membership was a separate scan is gone.
- The census witness drops that argument and the two fixtures only it used.
- gunbc.emit_summary_map_consumer_partition: is_known_variant no longer reads
  the summary map, so its consumer row leaves; its guard row stays, re-worded
  (the key set is still quantified over every enum summary).
- gunbc.recurring_failure_mode emit_stage_cost_dominates_its_closure gains the
  attribution for the v2.compiler.compile closure, scoped to that closure.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-28T19:11:06.716613Z 3b5fdf6 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

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