Skip to content

perf: Replace biome manifest parsing with a span-tracking scanner - #13255

Merged
anthonyshew merged 1 commit into
shew/defer-transitive-closuresfrom
shew/package-json-fast-parse
Jul 6, 2026
Merged

anthonyshew merged 1 commit into
shew/defer-transitive-closuresfrom
shew/package-json-fast-parse

Conversation

@anthonyshew

@anthonyshew anthonyshew commented Jul 5, 2026 •

Copy link
Copy Markdown
Contributor

Why

Manifest parsing sits on the critical path of every run: one parse per workspace package. The general-purpose biome CST parser earns its ~27µs/manifest through error recovery machinery that does nothing useful on valid manifests — which is nearly every manifest in every repo. A purpose-built scanner produces the same values, the same spans, and equivalent errors in ~1-2µs.

What

crate::manifest_parser: a single-pass, fully validating JSON scanner that builds PackageJson directly. It is the only parse path — no tiering, no fallback — and the biome deserializer plus its manifest types are deleted outright. biome and turborepo-unescape drop out of the crate's dependency tree entirely.

  • Spans preserved: Spanned fields carry the value token's full source range (quotes/braces included), so miette snippets in downstream diagnostics — packageManager mismatch, devEngines validation (including key-search sub-spans), recursive-turbo — keep their highlighted snippets. Parse errors point at the offending token. The preexisting span-assertion tests pass unchanged.
  • Acceptance contract: strict JSON, tolerated leading BOM, duplicate keys last-win, explicit null is a type error in typed fields but a valid devEngines declaration. Known change: serde_json's 128-level nesting limit applies when materializing unstructured field values.
  • Self-contained tests: the behavior contract is pinned by dependency-agnostic tests asserting parsed values, exact byte ranges (including BOM-offset alignment), attached text/path metadata, and accept/reject decisions across ~45 acceptance and malformed-input cases — escapes, duplicates, bad numbers, bad escapes, mismatched delimiters, control characters, type errors.
  • Adds workspace_discovery/manifest_parse/add_packages spans to break down parse_package_jsons in --profile output (this breakdown located the cost).

How to verify

  • cargo test -p turborepo-repository — 289 tests, including all preexisting package-manager span assertions, unchanged.
  • Measured on a 1191-package monorepo (interleaved A/B, 8 runs, medians): manifest parse wall 29ms → 8.8ms, parser CPU 46-60ms → 3ms (residue is turbo.json parsing, a separate code path), TTFT 258.7ms → 250.4ms. --dry=json byte-identical.

Stacked on #13250. Compounds with #13251, which removes the sequential turbo.json stats dominating the same discovery phase.

@anthonyshew
anthonyshew requested a review from a team as a code owner July 5, 2026 02:36
@anthonyshew
anthonyshew requested review from tknickman and removed request for a team July 5, 2026 02:36
@vercel

vercel Bot commented Jul 5, 2026 •

Copy link
Copy Markdown
Contributor

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

Project Deployment Actions Updated (UTC)
examples-basic-web Ready Ready Preview, Comment, Open in v0 Jul 5, 2026 3:18am
examples-designsystem-docs Ready Ready Preview, Comment, Open in v0 Jul 5, 2026 3:18am
examples-gatsby-web Ready Ready Preview, Comment, Open in v0 Jul 5, 2026 3:18am
examples-kitchensink-blog Ready Ready Preview, Comment, Open in v0 Jul 5, 2026 3:18am
examples-nonmonorepo Ready Ready Preview, Comment, Open in v0 Jul 5, 2026 3:18am
examples-svelte-web Ready Ready Preview, Comment, Open in v0 Jul 5, 2026 3:18am
examples-tailwind-web Ready Ready Preview, Comment, Open in v0 Jul 5, 2026 3:18am
examples-vite-web Ready Ready Preview, Comment, Open in v0 Jul 5, 2026 3:18am
turbo-site Ready Ready Preview, Comment, Open in v0 Jul 5, 2026 3:18am
turborepo-eve-agent Ready Ready Preview, Comment, Open in v0 Jul 5, 2026 3:18am

@anthonyshew
anthonyshew force-pushed the shew/package-json-fast-parse branch from 4588d7f to 5407d4b Compare July 5, 2026 03:03
@anthonyshew anthonyshew changed the title perf: Parse strict-JSON manifests with serde, falling back to biome perf: Replace biome manifest parsing with a span-tracking scanner Jul 5, 2026
Manifest parsing sits on the critical path of every run: one parse per
workspace package. The general-purpose biome CST parser spent ~27us per
manifest building a full syntax tree with error recovery; a purpose-built
single-pass scanner extracts exactly what PackageJson needs in ~1-2us.

Diagnostics keep their fidelity: Spanned fields carry the value token's
full source range, so miette snippets in downstream errors
(packageManager mismatches, devEngines validation, recursive turbo
invocations) render with highlighted snippets as before, and parse
errors point at the offending token.

The biome deserializer and its manifest types are deleted outright;
biome and turborepo-unescape drop out of the crate's dependency tree
entirely. The parser's behavior contract is pinned by self-contained
tests asserting values, exact byte ranges, attached metadata, and
accept/reject decisions directly. serde_json's 128-level nesting limit
applies when materializing unstructured field values.

Also adds workspace_discovery/manifest_parse/add_packages spans to break
down the package graph build phase in --profile output.

On a 1191-package monorepo: manifest parse wall 29ms -> 8.8ms, parser
CPU 46-60ms -> 3ms, TTFT median 258.7ms -> 250.4ms. Dry-run JSON is
byte-identical.
@anthonyshew
anthonyshew force-pushed the shew/package-json-fast-parse branch from 5407d4b to 577c820 Compare July 5, 2026 03:16
@anthonyshew
anthonyshew merged commit 47f5e0c into shew/defer-transitive-closures Jul 6, 2026
43 checks passed
@anthonyshew
anthonyshew deleted the shew/package-json-fast-parse branch July 6, 2026 12:24

This branch was successfully deployed

1 active deployment
Preview – turborepo-eve-agent — 577c8202 Deployed Jul 5, 2026 by vercel[bot]
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