Skip to content

perf!: speed up parsing with token lookups, shared kept tokens and a boxed Star - #42

Draft
kvlonge wants to merge 2 commits into
mainfrom
perf/parse-throughput
Draft

kvlonge wants to merge 2 commits into
mainfrom
perf/parse-throughput

Conversation

@kvlonge

@kvlonge kvlonge commented Nov 2, 2026

Copy link
Copy Markdown

Why

Parsing dominates SQL lint cost in downstream users: tokenize plus parse is about two thirds of lint instructions. Profiling showed per-token hashing for single character tokens, a full token copy when parsing from kept tokens, and heavy memcpy because every Expression was 232 bytes due to the unboxed Star variant.

Changes

  • Tokenizer: array lookups for single character tokens and identifier quotes instead of hashing per token.
  • Parser::with_config_from_tokens(sql, &[Token], config) builds parser tokens that share kept token text instead of cloning the token vector.
  • Breaking (Rust API): Expression::Star now holds Box<Star>, shrinking Expression from 232 to 96 bytes. Construct it with Expression::Star(Box::new(star)) or Expression::star(). Pattern matches on Expression::Star(_) are unaffected. Serde output is unchanged because Box<T> serializes like T, so JSON, Python, WASM and FFI ASTs keep the same shape.

Verification

  • Lint batch of 2,249 requests: instructions 12.94 G to 11.17 G (about 14 percent fewer), CPU about 1.60 s to 1.35 s. Diagnostics byte-identical with default rules and with all 53 rules enabled.
  • Downstream compile of a 3,000 model project: wall 6.47 s to 6.07 s, CPU 15.05 s to 13.54 s, RSS flat. Compile JSON and compiled output identical; compiler differential over 391 projects passed.
  • Downstream Rust workspace tests: 1,057 passed. Downstream Python unit and integration tests: 11,727 passed; 6 signal timing failures reproduce identically without this change.
  • Local cargo fmt --check and cargo check -p polyglot-sql --tests pass. The full polyglot suite could not compile locally (8 GB memory), so this draft relies on CI for core, release-fixtures, bindings and feature-gates.

kvlonge and others added 2 commits November 2, 2026 17:32
Expression::Star held Star inline, which made every Expression 232 bytes.
Boxing it shrinks Expression to 96 bytes and removes most memcpy traffic
when parsing.

BREAKING CHANGE: Expression::Star now holds Box<Star>. Construct it with
Expression::Star(Box::new(star)) or Expression::star(). Serialized JSON is
unchanged.

Co-authored-by: Kevin Longe <kvlonge@gmail.com>
Amp-Thread-ID: https://ampcode.com/threads/T-01a18b8a-340f-717d-9ca7-6dcf564a065a

This branch has not been deployed

No deployments
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