Skip to content

fix(track-memory-allocations): reserve transform scoping capacity#22621

Merged
graphite-app[bot] merged 1 commit into
mainfrom
codex/fix-track-memory-allocs
May 20, 2026
Merged

fix(track-memory-allocations): reserve transform scoping capacity#22621
graphite-app[bot] merged 1 commit into
mainfrom
codex/fix-track-memory-allocs

Conversation

@Dunqing

@Dunqing Dunqing commented May 20, 2026

Copy link
Copy Markdown
Member

Issue

The Allocations CI job can fail on PRs that do not touch the transformer because cargo allocs can rewrite allocs_transformer.snap differently across platforms. In the observed failure, Linux x64 reported one extra transformer system allocation for App.tsx, while macOS/arm64 still reported the old count.

Why

The allocation tracker was passing transformer a Scoping built differently from the production compiler path. Production builds semantic data with SemanticBuilder::with_excess_capacity(2.0) before running transforms, because transforms may add scopes, symbols, and references. The allocation tracker did not reserve that extra semantic capacity.

That made the transformer snapshot accidentally include growth of semantic scoping storage. In this case, JSX automatic runtime import generation creates a new root-scope binding. The traced Linux-only allocation happened under JsxImpl::get_create_element -> AutomaticModuleBindings::import_jsx -> TraverseScoping::add_binding -> Scoping::create_symbol, when pushing the generated symbol forced the semantic Scoping arena to allocate another chunk.

Linux got a different allocation count because this is a capacity-boundary effect, not different transformer behavior. The Scoping arena layout depends on target layout and alignment. On Linux x64, the generated binding crossed the arena chunk boundary and allocated a new 16-byte-aligned chunk, so the measured transformer count became 27. On macOS/arm64, the same push still fit in the existing semantic arena capacity, so the measured count stayed 26.

So the root cause is that transformer allocation tracking was measuring platform-sensitive semantic storage growth. Any unrelated PR could expose the same stale snapshot whenever CI regenerated allocations on a platform that lands on the other side of that capacity boundary.

Fix

Keep allocs_semantic.snap measuring regular semantic analysis, but build a separate production-like semantic Scoping for transformer measurement using with_excess_capacity(2.0). This matches the compiler and transformer benchmarks, and removes the semantic arena capacity cliff from the transformer allocation snapshot.

The transformer allocation snapshot is regenerated after the measurement fix.

Validation

Verified cargo allocs leaves the branch clean on macOS/arm64 and in Linux amd64 Docker.

AI usage: I used AI assistance to investigate, implement, and validate this change.

@Dunqing Dunqing requested review from camc314 and leaysgur May 20, 2026 09:55
@Dunqing Dunqing marked this pull request as ready for review May 20, 2026 09:59
@Dunqing Dunqing added the 0-merge Merge with Graphite Merge Queue label May 20, 2026

Dunqing commented May 20, 2026

Copy link
Copy Markdown
Member Author

Merge activity

…2621)

## Issue

The `Allocations` CI job can fail on PRs that do not touch the transformer because `cargo allocs` can rewrite `allocs_transformer.snap` differently across platforms. In the observed failure, Linux x64 reported one extra transformer system allocation for `App.tsx`, while macOS/arm64 still reported the old count.

## Why

The allocation tracker was passing transformer a `Scoping` built differently from the production compiler path. Production builds semantic data with `SemanticBuilder::with_excess_capacity(2.0)` before running transforms, because transforms may add scopes, symbols, and references. The allocation tracker did not reserve that extra semantic capacity.

That made the transformer snapshot accidentally include growth of semantic scoping storage. In this case, JSX automatic runtime import generation creates a new root-scope binding. The traced Linux-only allocation happened under `JsxImpl::get_create_element -> AutomaticModuleBindings::import_jsx -> TraverseScoping::add_binding -> Scoping::create_symbol`, when pushing the generated symbol forced the semantic `Scoping` arena to allocate another chunk.

Linux got a different allocation count because this is a capacity-boundary effect, not different transformer behavior. The `Scoping` arena layout depends on target layout and alignment. On Linux x64, the generated binding crossed the arena chunk boundary and allocated a new 16-byte-aligned chunk, so the measured transformer count became 27. On macOS/arm64, the same push still fit in the existing semantic arena capacity, so the measured count stayed 26.

So the root cause is that transformer allocation tracking was measuring platform-sensitive semantic storage growth. Any unrelated PR could expose the same stale snapshot whenever CI regenerated allocations on a platform that lands on the other side of that capacity boundary.

## Fix

Keep `allocs_semantic.snap` measuring regular semantic analysis, but build a separate production-like semantic `Scoping` for transformer measurement using `with_excess_capacity(2.0)`. This matches the compiler and transformer benchmarks, and removes the semantic arena capacity cliff from the transformer allocation snapshot.

The transformer allocation snapshot is regenerated after the measurement fix.

## Validation

Verified `cargo allocs` leaves the branch clean on macOS/arm64 and in Linux amd64 Docker.

AI usage: I used AI assistance to investigate, implement, and validate this change.
@graphite-app graphite-app Bot force-pushed the codex/fix-track-memory-allocs branch from 59df140 to b9171ea Compare May 20, 2026 10:05
@graphite-app graphite-app Bot merged commit b9171ea into main May 20, 2026
27 checks passed
@graphite-app graphite-app Bot removed the 0-merge Merge with Graphite Merge Queue label May 20, 2026
@graphite-app graphite-app Bot deleted the codex/fix-track-memory-allocs branch May 20, 2026 10:09
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.

2 participants