Skip to content

chore(tools): add tools_compile_profile — salsa/pipeline profiling harness - #4038

Merged
hellovai merged 3 commits into
canaryfrom
perf/tools-compile-profile
Jul 16, 2026
Merged

chore(tools): add tools_compile_profile — salsa/pipeline profiling harness#4038
hellovai merged 3 commits into
canaryfrom
perf/tools-compile-profile

Conversation

@hellovai

@hellovai hellovai commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Summary

Provenance: #4016. The remaining findings from that audit are being re-landed as small independent PRs measured with this tool.

Baseline on current canary (2660b8b)

Protocol: cargo build --release -p tools_compile_profile, then
./target/release/tools_compile_profile baml_language/crates/baml_tests/baml_src --repeat 5
with BAML_NO_BYTECODE_CACHE=1 and BAML_CACHE_DIR pointed at a fresh temp dir (so #3924's disk cache is out of the picture). Corpus: 77 files, 25,212 lines. Apple Silicon, single-threaded, medians of 5 cold runs.

phase median
check 1.089 s
emit (bytecode) 1.330 s
total 2.420 s (min 2.385, mean 2.442, max 2.524)

For comparison, #4016's pre-optimization baseline on this corpus was 16.0s and its final state ~0.50s. Canary's own movement (#4032 deleting the old TIR type algebra, #3924's caching work) already brought cold compile from 16.0s to ~2.4s; the still-orthogonal optimizations from #4016 target the remainder.

Top 10 queries by executions (cold, representative run)

exec query
15,590 infer_scope_types
2,262 function_in_scope_generic_param_bounds
2,256 function_body
2,131 callable_throws
625 class_generic_param_bounds
477 resolve_class_fields
419 function_parameter_defaults
419 function_signature
147 impl_data
147 impl_data_source_map

25,972 total query executions; TIR is 18,697 of them (72%).

Test plan

  • cargo build --release -p tools_compile_profile clean
  • Clean run against baml_language/crates/baml_tests/baml_src (--repeat 5)
  • Pre-commit hooks: cargo fmt, workspace clippy (-D warnings), cargo stow, markdown validation

Made with Cursor

Summary by CodeRabbit

  • New Features
    • Introduced a standalone compiler profiling harness to measure compilation phase timings and query execution/caching behavior, including cold vs warm runs.
    • Generates human-readable and JSON reports, with optional compact summary output and validation-only mode.
  • Documentation
    • Added comprehensive documentation covering CLI usage, report interpretation, flamegraph pairing guidance, and profiling methodology.
  • Tests
    • Added tests for query-to-phase mapping and report-related behavior.

…rness

Standalone black-box profiler for the compiler pipeline (parse → HIR →
PPIR → TIR → MIR → emit): wall-clock per phase, per-query execution and
cache-hit counts via salsa::Event callbacks, cold/warm run comparison,
JSON output. Ported from PR #4016 (perf/compiler2-cold-compile); the
PROF_* TIR audit counters that only existed on that branch are dropped,
and the audit README section is annotated as a historical record
predating #4032/#3924.

Co-authored-by: Cursor <cursoragent@cursor.com>
@cursor

cursor Bot commented Jul 15, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@vercel

vercel Bot commented Jul 15, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
beps Ready Ready Preview, Comment Jul 16, 2026 1:44am
promptfiddle Ready Ready Preview, Comment Jul 16, 2026 1:44am
promptfiddle2 Ready Ready Preview, Comment Jul 16, 2026 1:44am

Request Review

@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: fd967190-0acc-409c-95c8-a4aff307e073

📥 Commits

Reviewing files that changed from the base of the PR and between 6dda35b and 5e65f13.

📒 Files selected for processing (1)
  • baml_language/Cargo.toml

📝 Walkthrough

Walkthrough

Adds a standalone Rust profiling harness for the BAML compiler. It measures cold and warm pipeline timings, Salsa query activity, diagnostics, and phase distribution, with human-readable, JSON, and summary-line outputs plus usage documentation.

Changes

Compiler profiling harness

Layer / File(s) Summary
Tool crate and workspace wiring
baml_language/Cargo.toml, baml_language/crates/tools_compile_profile/Cargo.toml, baml_language/stow.toml
Registers the new binary crate, workspace dependencies, allocator, lint settings, and approved compile namespace prefix.
Profiling pipeline and query accounting
baml_language/crates/tools_compile_profile/src/main.rs
Discovers BAML sources, runs cold and warm compiler pipelines, captures Salsa events, resolves query names, classifies queries by compiler phase, and tests phase mapping.
Reports and operating documentation
baml_language/crates/tools_compile_profile/src/main.rs, baml_language/crates/tools_compile_profile/README.md
Produces human-readable, JSON, and compact summary outputs, and documents usage, cache behavior, interpretation, sampling, audit results, and limitations.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CLI as tools_compile_profile CLI
  participant Sources as BAML source loader
  participant DB as ProjectDatabase
  participant Events as Salsa EventCallback
  participant Report as Report formatter
  CLI->>Sources: discover and read .baml sources
  CLI->>DB: build database and inputs
  DB->>Events: emit query and cycle events
  CLI->>DB: run check and optional get_bytecode
  Events-->>CLI: return query counters
  CLI->>Report: format timing and query statistics
Loading

Possibly related PRs

  • BoundaryML/baml#4016: Overlapping additions for mimalloc, the profiling crate, and stow.toml prefix configuration.

Suggested reviewers: 2kai2kai2, sxlijin

Poem

I’m a rabbit with metrics tucked tight,
Counting Salsa queries by moonlight.
Cold runs hop, warm runs glow,
Reports bloom where timings flow.
mimalloc helps my burrow race—
Compile profiling finds its place!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: adding the tools_compile_profile Salsa/pipeline profiling harness.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch perf/tools-compile-profile

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@vercel
vercel Bot temporarily deployed to Preview – beps July 15, 2026 17:59 Inactive
@github-actions

Copy link
Copy Markdown

⏭️ Performance benchmarks were skipped

Perf benchmarks (CodSpeed) are opt-in on pull requests — they no longer run on every push. They always run automatically after merge to canary/main.

To run them on this PR, do any of the following, then push a commit (or re-run CI):

  • Add RUN_CODSPEED=1 to the PR description, or
  • Include run-perf or /perf in the PR title or any commit message.

@vercel
vercel Bot temporarily deployed to Preview – promptfiddle2 July 15, 2026 18:06 Inactive
@github-actions

github-actions Bot commented Jul 15, 2026

Copy link
Copy Markdown

Binary size checks passed

7 passed

Artifact Platform File Gzip Gated on Baseline Delta Status
baml-cli Linux 🔒 22.8 MB 9.7 MB file 22.8 MB +48.3 KB (+0.2%) OK
packed-program Linux 🔒 16.3 MB 6.8 MB file 16.3 MB +16.4 KB (+0.1%) OK
baml-cli macOS 🔒 17.5 MB 8.5 MB file 17.5 MB +33.2 KB (+0.2%) OK
packed-program macOS 🔒 12.6 MB 6.0 MB file 12.6 MB -16.5 KB (-0.1%) OK
baml-cli Windows 🔒 19.1 MB 8.7 MB file 18.7 MB +406.0 KB (+2.2%) OK
packed-program Windows 🔒 13.5 MB 6.1 MB file 13.5 MB -2.6 KB (-0.0%) OK
bridge_wasm WASM 15.1 MB 🔒 4.3 MB gzip 4.3 MB +1.0 KB (+0.0%) OK

🔒 = the size this artifact is GATED on (ceiling + delta). Binaries gate on file size (installed binary); WASM gates on gzip (download size). The other size is shown for information only.


Generated by cargo size-gate · workflow run

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (1)
baml_language/crates/tools_compile_profile/src/main.rs (1)

524-643: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add unit tests for resolve_query_names and phase_for_query.

Both are pure, logic-bearing functions (collision-suffix disambiguation, phase classification) with no test coverage. As per coding guidelines, Rust changes should prefer unit tests over integration tests where possible — a small #[cfg(test)] mod tests in this file covering a couple of known query names (phase mapping + fallback to "other") and a synthetic name collision would guard this logic cheaply as the query list evolves.

Based on coding guidelines: "Prefer writing Rust unit tests over integration tests where possible" (**/*.rs).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@baml_language/crates/tools_compile_profile/src/main.rs` around lines 524 -
643, Add a #[cfg(test)] module in the same Rust file covering phase_for_query
with known lexer/compiler query mappings and the "other" fallback, plus
resolve_query_names with synthetic colliding ingredient names and distinct
indexed suffixes. Use focused unit-test fixtures for ProjectDatabase and
RawStats, preserving the existing sorting and disambiguation behavior.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@baml_language/crates/tools_compile_profile/README.md`:
- Line 133: Update the sample-output code fence in the README to use the text
language tag (```text) instead of an untyped fence, preserving the sample
content unchanged.
- Around line 84-85: Update the usage documentation for tools_compile_profile to
state that the CLI accepts directories containing .baml files, a baml_src/
directory, or baml.toml project roots, while preserving the existing invocation
example.
- Around line 47-64: The README’s cache-mode description incorrectly labels
every measured run as cold and warm invocations as cache-exclusive. Update the
“Cache mode: cold by default” section to state that only the first invocation
for each fresh ProjectDatabase is cold, while --warm-runs reuses Salsa
memoization but still performs uncached wrapper work; revise the warm-run
explanation consistently and preserve the existing database lifecycle details.
- Around line 73-74: Update the benchmark statements in README.md around the
emit and related benchmark sections to label the 13.6s/12.1s and
16.0s/8.1s/13.2s figures as historical runs, or replace them with current
measurements consistent with the documented ~0.5s compile time. Ensure readers
can clearly distinguish historical audit data from present-day performance.

In `@baml_language/crates/tools_compile_profile/src/main.rs`:
- Around line 470-497: Update the emit gate around error_count and
get_bytecode() to consider only user-file error diagnostics, matching
get_bytecode()’s existing behavior rather than counting compiler2 builtin
errors. Reuse the same diagnostic filter or delegate the decision to
get_bytecode(), while preserving check-only handling and warning counting.

---

Nitpick comments:
In `@baml_language/crates/tools_compile_profile/src/main.rs`:
- Around line 524-643: Add a #[cfg(test)] module in the same Rust file covering
phase_for_query with known lexer/compiler query mappings and the "other"
fallback, plus resolve_query_names with synthetic colliding ingredient names and
distinct indexed suffixes. Use focused unit-test fixtures for ProjectDatabase
and RawStats, preserving the existing sorting and disambiguation behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 92a2a54e-4032-4aa2-ab50-4df03e7ebedc

📥 Commits

Reviewing files that changed from the base of the PR and between 2660b8b and c19d6fd.

⛔ Files ignored due to path filters (1)
  • baml_language/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (5)
  • baml_language/Cargo.toml
  • baml_language/crates/tools_compile_profile/Cargo.toml
  • baml_language/crates/tools_compile_profile/README.md
  • baml_language/crates/tools_compile_profile/src/main.rs
  • baml_language/stow.toml

Comment thread baml_language/crates/tools_compile_profile/README.md Outdated
Comment thread baml_language/crates/tools_compile_profile/README.md
Comment thread baml_language/crates/tools_compile_profile/README.md Outdated
Comment thread baml_language/crates/tools_compile_profile/README.md Outdated
Comment thread baml_language/crates/tools_compile_profile/src/main.rs
…g, unit tests

Addresses CodeRabbit review feedback on the tools_compile_profile PR:

- Emit gate now mirrors get_bytecode(): only user-file check errors abort
  emit. db.check() also covers compiler2 builtin stub files whose diagnostics
  never block codegen, so the previous 'any error' gate could skip emit even
  when bytecode generation would have proceeded. Total error/warning counts
  are still reported unfiltered.
- Clarify cold-vs-warm measurement semantics in the README and module doc:
  only the first (cold) invocation fills the cache; warm invocations hit a
  warm query cache but still pay uncached wrapper cost (db.check() /
  db.get_bytecode() materialization).
- README: document project-root (baml_src/, alongside baml.toml) input form;
  add a 'text' language tag to the sample-output fence (markdownlint MD040).
- Add unit tests for phase_for_query (known phase mappings, 'other' fallback,
  and collision-suffix stripping).

Co-authored-by: Cursor <cursoragent@cursor.com>
@hellovai

Copy link
Copy Markdown
Contributor Author

Addressed the review feedback in 6dda35b:

  1. Emit gate mirrors get_bytecode() (Major). The gate now counts only user-file errors, matching get_bytecode()'s assert_no_diagnostic_errors semantics. db.check() also covers compiler2 builtin stub files, so the previous "any error" gate could have skipped emit even when codegen would proceed. Total error/warning counts are still reported unfiltered.
  2. Cold vs warm wording. README + module doc now state that only the first (cold) invocation fills the cache; warm invocations hit a warm query cache but still pay the uncached wrapper cost (db.check() / db.get_bytecode() materialization/walking/cloning), which is exactly what the cold-vs-warm table isolates.
  3. baml.toml / project roots. README usage now documents pointing at a project root (a dir with baml_src/, typically alongside baml.toml).
  4. MD040. The sample-output fence now uses ```text.
  5. Unit tests. Added #[cfg(test)] tests for phase_for_query covering known phase mappings, the "other" fallback, and collision-suffix stripping.

On the suggestion to also unit-test resolve_query_names: I skipped that one. Its only non-trivial logic is the collision-suffix disambiguation, which is keyed on salsa::IngredientIndex values that aren't publicly constructible, and the rest is a thin wrapper over db.ingredient_debug_name(...). A meaningful test would need a live ProjectDatabase with real ingredients (integration-level), so it's exercised by actual profiler runs rather than a synthetic unit fixture. The suffix-stripping half is now covered indirectly via phase_for_query_strips_collision_suffix.

Verified locally: cargo clippy -p tools_compile_profile --all-targets -- -D warnings clean, cargo test -p tools_compile_profile green, and a full profiler run still emits bytecode (0 user-file errors → emit proceeds). Pre-commit hooks (fmt, clippy, markdown) passed.

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

@hellovai Thanks for the detailed writeup — all five points look solid, especially the emit-gate fix now correctly mirroring get_bytecode()'s user-file-only semantics. The reasoning for skipping a synthetic unit test on resolve_query_names (given IngredientIndex isn't publicly constructible) makes sense; the indirect coverage via phase_for_query_strips_collision_suffix is a reasonable compromise.

Kicking off a fresh review of the updated code now.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@vercel
vercel Bot temporarily deployed to Preview – beps July 16, 2026 01:10 Inactive

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
baml_language/crates/tools_compile_profile/README.md (1)

255-260: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Reconcile the on-disk cache claims.

Lines 184-192 state that upstream change #3924 added content-addressed on-disk incremental caching, but this section says the compiler has no on-disk cache and every baml check is cold. Clarify that the profiler intentionally uses a fresh in-memory database and does not exercise the compiler’s on-disk cache, or update the historical wording.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@baml_language/crates/tools_compile_profile/README.md` around lines 255 - 260,
Reconcile the historical caching statement around the profiler description with
the “What's deliberately NOT here” section: clarify that the profiler uses a
fresh in-memory Salsa database and therefore does not exercise the compiler’s
content-addressed on-disk cache, while preserving the distinction between
profiler behavior and compiler capabilities.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@baml_language/crates/tools_compile_profile/README.md`:
- Around line 255-260: Reconcile the historical caching statement around the
profiler description with the “What's deliberately NOT here” section: clarify
that the profiler uses a fresh in-memory Salsa database and therefore does not
exercise the compiler’s content-addressed on-disk cache, while preserving the
distinction between profiler behavior and compiler capabilities.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 65bad91b-a413-4489-affd-fba869019b22

📥 Commits

Reviewing files that changed from the base of the PR and between c19d6fd and 6dda35b.

📒 Files selected for processing (2)
  • baml_language/crates/tools_compile_profile/README.md
  • baml_language/crates/tools_compile_profile/src/main.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • baml_language/crates/tools_compile_profile/src/main.rs

@vercel
vercel Bot temporarily deployed to Preview – promptfiddle2 July 16, 2026 01:18 Inactive
@hellovai
hellovai enabled auto-merge July 16, 2026 01:23
@vercel
vercel Bot temporarily deployed to Preview – beps July 16, 2026 01:23 Inactive
@vercel
vercel Bot temporarily deployed to Preview – promptfiddle2 July 16, 2026 01:30 Inactive
@vercel
vercel Bot temporarily deployed to Preview – promptfiddle July 16, 2026 01:44 Inactive
@hellovai
hellovai added this pull request to the merge queue Jul 16, 2026
Merged via the queue into canary with commit 708799d Jul 16, 2026
52 checks passed
@hellovai
hellovai deleted the perf/tools-compile-profile branch July 16, 2026 02:03
meefs pushed a commit to meefs/baml that referenced this pull request Jul 16, 2026
…ns (2.4s → 0.81s cold) (BoundaryML#4058)

Re-lands the still-orthogonal cold-compile optimizations from BoundaryML#4016,
re-derived from
scratch against current `canary` (which moved underneath BoundaryML#4016 via BoundaryML#4032
and BoundaryML#3924).
Not a rebase of BoundaryML#4016 — every change was re-derived and re-measured.
BoundaryML#4016's single
biggest win (recursive-alias hoist) is intentionally **not** here: BoundaryML#4032
already captured
it by deleting the old TIR `StructuralTy` algebra. The profiler itself
already landed
separately as BoundaryML#4038.

## Measurement

Corpus: `crates/baml_tests/baml_src` (77 files, 25,212 lines). Protocol:
`tools_compile_profile ... --repeat 5`, disk cache disabled
(`BAML_NO_BYTECODE_CACHE=1`,
fresh `BAML_CACHE_DIR`). Cold-cache medians of 5 runs, single-threaded.

| | check | emit | **total** |
|---|---|---|---|
| canary (`8c29c827e`) | 1.114 s | 1.277 s | **2.392 s** (min 2.354 /
max 2.537) |
| this branch | 0.462 s | 0.345 s | **0.808 s** (min 0.791 / max 0.828)
|

**3.0x faster** cold check+emit, single-threaded.

(For reference, the pre-BoundaryML#4032 baseline this work originally started from
was ~16 s; BoundaryML#4032
alone brought cold compile to a few seconds, and this branch takes it
under ~1 s.)

Key query-count deltas (cold, corpus): `infer_scope_types` 15,590 →
**13,331** (PPIR→HIR
`file_semantic_index` delegation removes duplicate scope inference);
`package_resolved_aliases`
/ `package_impl_locs` no longer rebuilt inside every one of those
inference calls (now a
handful of per-package executions); new memoized queries `file_ast`
(131, once/file),
`callee_generics_for_func` (1,834), tracked PPIR `function_body`.

## What's in it (one commit per track)

- **`file_ast` tracked query** — lower CST→AST once per file (items +
lowering diagnostics +
env refs), shared by both `file_semantic_index` queries,
`ppir_expansion_items`, the
project-wide expansion collectors, and the LSP check path; PPIR
`file_semantic_index`
delegates to HIR's when a file has no `$stream` expansions; PPIR
`function_body` tracked.
- **package-level TIR queries** — `package_resolved_aliases` (+
`cycle_initial` seeding an
empty env, mirroring `infer_scope_types` — it sits in a real salsa cycle
via
associated-type-projection alias RHS) and `package_impl_locs` as tracked
queries, plus
`callee_generics_for_func`, so the alias map / impl-block list / callee
generics stop
  being rebuilt per inference call.
- **nested-lambda inference projection** — lambda bodies were inferred
twice (inline in the
owner scope, then again by the standalone `ScopeKind::Lambda` query),
which also emitted
duplicate diagnostics inside lambdas. The inline pass now captures the
lambda's tables and
the Lambda arm projects them; synthetic desugared `test`/`testset`
bodies fall through to
standalone inference so their diagnostics are still emitted. Snapshot
updates where the
  duplicate lambda diagnostics disappear are the point.
- **MIR dispatch prefilter + subtype fast paths** —
`dispatch_target_for_concrete` gates its
per-call impl enumeration behind a package-wide `FxHashSet` of
interface-declared method
names (own package + dependency closure); `baml_type::normalize` gets a
reflexivity +
`heads_definitely_differ` fast-reject in `equivalent()` (conservative:
same-kind nominal
pairs only — List/EvolvingList collapse to the same canonical head
post-BoundaryML#4032) and
restricts `is_subtype_of` co-inductive assumption bookkeeping to the
expanding arms
(Mu / TypeVar / AssociatedTypeProjection) via `is_subtype_of_inner`,
with a termination
argument in-comment. Re-derived onto the post-BoundaryML#4032 `baml_type` algebra
(the only
  equivalence path now).
- **memoized `class_type_tags_for_project`** — the project-wide class →
type-tag map was
rebuilt (every file's item tree walked, every class name re-rendered and
re-hashed)
inside every `LoweringContext` construction, i.e. once per lowered
function (~420x on
the corpus; the hottest MIR frame in a CPU sample). Now a
`#[salsa::tracked]` query
keyed on the `Project` input; `LoweringContext` borrows it. This is
BoundaryML#4016 audit item BoundaryML#4,
initially assumed superseded by BoundaryML#3924's content-addressed tags — BoundaryML#3924
changed the tag
*values* but left the per-function rebuild in place. Also adds this PR
chain's new
  tracked queries to the profiler's `phase_for_query` table.
- **match usefulness report reuse + emit buffer pre-sizing** — match
checking ran the full
usefulness matrix twice per `match` (exhaustiveness, then an identical
second pass for
unreachable-arm detection whenever no arm had a pattern error); the
reachability pass now
reuses the exhaustiveness report (exhaustiveness: ~11% -> ~1.7% of CPU
inclusive).
`StackifyCodegen` pre-sizes its bytecode/meta buffers and local/block
maps from the MIR's
  shape instead of growing from empty per function.
- **CLI mimalloc + diagnostic rendering** — mimalloc as `baml_cli`'s
global allocator; build
the ariadne `SourceCache` once per diagnostic batch instead of once per
diagnostic. Verified
byte-for-byte identical rendered diagnostics and clean
`BAML_CACHE_VERIFY=1` (so BoundaryML#3924's
  cached-diagnostic replay does not diverge).

## Deliberately not re-landed

- The BoundaryML#4016 recursive-alias hoist — superseded by BoundaryML#4032.
- Skip-builtin-diagnostics — superseded by BoundaryML#3924's per-toolchain
builtin-diagnostics cache.

## Testing

Full workspace test suite green except two pre-existing/environmental
failures unrelated to
this change: a Python cancellation pytest that fails identically on
clean `canary` (local
Python < 3.11: `ExceptionGroup`/`CancelledError.reason`). `cargo fmt` +
`clippy -D warnings`
clean.

Provenance: BoundaryML#4016 (reference implementation, kept as reference, not
merged).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
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