Skip to content

perf: parallel cold checks that actually scale + flat LSP latency#4100

Closed
hellovai wants to merge 1 commit into
hellovai/compiler-perf-fixesfrom
hellovai/compiler-parallel-load-lsp
Closed

perf: parallel cold checks that actually scale + flat LSP latency#4100
hellovai wants to merge 1 commit into
hellovai/compiler-perf-fixesfrom
hellovai/compiler-parallel-load-lsp

Conversation

@hellovai

Copy link
Copy Markdown
Contributor

Stacked on #4098. Fixes the "12 threads = 1.18× speedup" wall, diagnosed by comparing our salsa usage against ty/ruff's (our driver pattern was already identical to theirs — the problem was one query shape).

What

  1. Prime wave: every file's PPIR semantic index is computed across workers before the per-file check fan-out. Whole-package aggregates (package_items/namespace_items) fold over every file's index; on a cold db the first worker to claim that memo computed parse+lower+index for the entire project inline on one thread while all other workers parked on the memo's sync slot. Also retires the old first-file warm-up, which warmed the builtin package, not the user package.
  2. Bulk project load: add_or_update_files writes the project file list once (the per-file path re-cloned the whole Vec and bumped the salsa revision per file — O(files²) during load); source reads are parallel with discovery order preserved (FileId assignment and diagnostic ordering unchanged).
  3. LSP: the diagnostics candidate checks files through the shared order-preserving parallel checker under the held source guard, so every per-edit path gets the parallelism + prime wave.

End-user impact (measured)

before after
cold pure check, 295k LOC (12 threads) 7.4 s (~1.2 cores) 2.8 s (2.4+ cores)
cold check+seed, 295k LOC 10.5 s 4.4 s
LSP edit→diagnostics, 250 files 464 ms 172 ms
LSP edit→diagnostics, 500 files 1.7 s 176 ms
LSP edit→diagnostics, 1000 files 5.5 s 209 ms

Editor latency is now ~flat in project size.

Verification

  • Diagnostics byte-identical to the previous binary on the error-corpus (cold + warm).
  • 198 tests pass across baml_project / bex_project / baml_cli.
  • LSP load test: 8+ runs at 250/1000 files with 50-edit multi-file burst storms and 20 s of ~17 edits/s churn — zero crashes, stable RSS (~810 MB peak @1000), post-storm convergence every time. Disclosure: the first two 1000-file runs (only, immediately after a large build finished) showed a warm-up stall that has not reproduced in 8 subsequent attempts including exact-condition replays; the stress harness now captures server log traces to identify the stage if it recurs.

Not in this PR: ty-style snapshot+cancellation for the LSP (blocked on the panic = "abort" release profile — cancellation requires unwinding; needs a product decision), and the warm-edit floor (throws-gate + unit loads; separate reviewed design).

🤖 Generated with Claude Code

https://claude.ai/code/session_01V4oee6wrCHzXH6mM2h8eJo

@vercel

vercel Bot commented Jul 21, 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 22, 2026 3:39am
promptfiddle Ready Ready Preview, Comment Jul 22, 2026 3:39am
promptfiddle2 Ready Ready Preview, Comment Jul 22, 2026 3:39am

Request Review

@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.

@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown

Binary size checks passed

7 passed

Artifact Platform File Gzip Gated on Baseline Delta Status
baml-cli Linux 🔒 25.6 MB 10.9 MB file 25.3 MB +335.0 KB (+1.3%) OK
packed-program Linux 🔒 17.3 MB 7.1 MB file 17.0 MB +218.6 KB (+1.3%) OK
baml-cli macOS 🔒 19.9 MB 9.5 MB file 19.6 MB +281.3 KB (+1.4%) OK
packed-program macOS 🔒 13.5 MB 6.2 MB file 13.2 MB +231.5 KB (+1.8%) OK
baml-cli Windows 🔒 21.4 MB 9.7 MB file 21.1 MB +278.0 KB (+1.3%) OK
packed-program Windows 🔒 14.4 MB 6.3 MB file 14.2 MB +200.7 KB (+1.4%) OK
bridge_wasm WASM 16.3 MB 🔒 4.4 MB gzip 4.4 MB +23.6 KB (+0.5%) 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

…roject load; parallel LSP sweep

Three fixes for the "12 threads = 1.18x" cold-check scaling wall,
diagnosed by comparing against ty/ruff's salsa usage (whose driver
pattern ours already matches):

- Prime wave: compute every file's PPIR semantic index across workers
  BEFORE fanning out per-file checks. Whole-package aggregate queries
  (package_items / namespace_items) fold over every file's index, and
  every file's check demands them - on a cold database the first
  worker to claim the aggregate memo computed parse+lowering+indexing
  for the entire project inline on one thread while all other workers
  parked on that memo's sync slot. With per-file indexes primed the
  aggregate fold is cheap and workers stay busy. Also replaces the
  old first-file serial warm-up, which warmed the builtin package
  (compiler2_all_files orders builtins first), not the user package.

- Bulk project load: add_or_update_files registers all sources with
  ONE project-file-list write; the per-file path cloned and re-set
  the whole files Vec and bumped the salsa revision once per file
  (O(files^2) copies during initial load). Source reads now happen
  across worker threads, preserving discovery order so FileId
  assignment and diagnostic ordering are unchanged.

- The LSP diagnostics candidate now checks files through the shared
  order-preserving parallel checker (under the held source guard -
  the same exclusion the serial loop relied on), so every per-edit
  path inherits the parallelism and the prime wave.

check_files_parallel returns per-file results in input order so the
LSP can zip them back to documents; the flat collector delegates.

Measured (Apple Silicon, 12 cores):
- cold pure check, 295k LOC: 7.4s -> 2.8s wall (1.2 -> 2.4+ cores)
- cold check+seed, 295k LOC: 10.5s -> 4.4s; 59k LOC: ~0.9s
- LSP edit->diagnostics: 250 files 464 -> 172ms; 500 files 1.7s ->
  176ms; 1000 files 5.5s -> 209ms (now ~flat in project size)
- LSP load test: burst storms + sustained churn at 250/1000 files,
  zero crashes, stable RSS, convergence after every storm

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V4oee6wrCHzXH6mM2h8eJo
@hellovai
hellovai force-pushed the hellovai/compiler-parallel-load-lsp branch from c2da018 to f214619 Compare July 22, 2026 03:17
@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: da4b74e8-33a7-4fac-bb55-f17e5b0a5cf3

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch hellovai/compiler-parallel-load-lsp

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.

@hellovai

Copy link
Copy Markdown
Contributor Author

Consolidated into #4105 (the full stack, rebased onto current canary, all CI green there). This PR's commits are contained in #4105 verbatim — closing in favor of one merge.

@hellovai hellovai closed this Jul 23, 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