Skip to content

perf(parser): fast path identifier parsing and inline operator helpers#22650

Merged
graphite-app[bot] merged 1 commit into
mainfrom
11-04-perf_parser_fast_path_identifier_kind_and_inline_operator_helpers
May 21, 2026
Merged

perf(parser): fast path identifier parsing and inline operator helpers#22650
graphite-app[bot] merged 1 commit into
mainfrom
11-04-perf_parser_fast_path_identifier_kind_and_inline_operator_helpers

Conversation

@Boshen

@Boshen Boshen commented May 21, 2026

Copy link
Copy Markdown
Member

Summary

Two small but compounding hot-path wins in the parser:

  • parse_identifier_kind fast path — for unescaped identifiers (the common case), slice directly from source text via token_source instead of going through lexer.get_string(), which dispatches on Kind. This is the same approach as Cam's earlier branch (03-31-perf_parser_fast_path_in_parse_identifier_kind...) that never landed.
  • #[inline] on operator helperskind_to_precedence, map_binary_operator, map_logical_operator, map_unary_operator, map_update_operator, map_assignment_operator. They're called from the Pratt loop in parse_binary_expression_rest but lived in a sibling module where rustc wouldn't auto-inline them.

Benchmarks

Criterion medians (baseline → patched, lower is better):

File Baseline Patched Δ
parser/binder.ts 433.60 µs 425.28 µs ~1.9%
parser/kitchen-sink.tsx 3.5702 ms 3.5368 ms ~0.9%
parser/cal.com.tsx 3.9827 ms 3.9519 ms ~0.8%
estree_tokens/checker.ts 9.6080 ms 9.5566 ms ~0.5%
estree/checker.ts 13.395 ms 13.373 ms ~0.2%

Identifier-dense TypeScript benefits the most, as expected — binder.ts is mostly identifiers.

Notes

  • No allocation regression (cargo allocs snapshot unchanged).
  • cargo coverage -- parser still 100% on test262 (47115/47115 positive, 4588/4588 negative).
  • cargo test -p oxc_parser, cargo clippy, just fmt all clean.

🤖 Generated with Claude Code

@github-actions github-actions Bot added the A-parser Area - Parser label May 21, 2026
@codspeed-hq

codspeed-hq Bot commented May 21, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 57 untouched benchmarks
⏩ 3 skipped benchmarks1


Comparing 11-04-perf_parser_fast_path_identifier_kind_and_inline_operator_helpers (842a214) with main (78cf83f)

Open in CodSpeed

Footnotes

  1. 3 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@Boshen Boshen added the 0-merge Merge with Graphite Merge Queue label May 21, 2026

Boshen commented May 21, 2026

Copy link
Copy Markdown
Member Author

Merge activity

#22650)

## Summary

Two small but compounding hot-path wins in the parser:

- **`parse_identifier_kind` fast path** — for unescaped identifiers (the common case), slice directly from source text via `token_source` instead of going through `lexer.get_string()`, which dispatches on `Kind`. This is the same approach as Cam's earlier branch (`03-31-perf_parser_fast_path_in_parse_identifier_kind...`) that never landed.
- **`#[inline]` on operator helpers** — `kind_to_precedence`, `map_binary_operator`, `map_logical_operator`, `map_unary_operator`, `map_update_operator`, `map_assignment_operator`. They're called from the Pratt loop in `parse_binary_expression_rest` but lived in a sibling module where rustc wouldn't auto-inline them.

## Benchmarks

Criterion medians (baseline → patched, lower is better):

| File | Baseline | Patched | Δ |
| --- | --- | --- | --- |
| `parser/binder.ts` | 433.60 µs | 425.28 µs | **~1.9%** |
| `parser/kitchen-sink.tsx` | 3.5702 ms | 3.5368 ms | ~0.9% |
| `parser/cal.com.tsx` | 3.9827 ms | 3.9519 ms | ~0.8% |
| `estree_tokens/checker.ts` | 9.6080 ms | 9.5566 ms | ~0.5% |
| `estree/checker.ts` | 13.395 ms | 13.373 ms | ~0.2% |

Identifier-dense TypeScript benefits the most, as expected — `binder.ts` is mostly identifiers.

## Notes

- No allocation regression (`cargo allocs` snapshot unchanged).
- `cargo coverage -- parser` still 100% on test262 (47115/47115 positive, 4588/4588 negative).
- `cargo test -p oxc_parser`, `cargo clippy`, `just fmt` all clean.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
@graphite-app graphite-app Bot force-pushed the 11-04-perf_parser_fast_path_identifier_kind_and_inline_operator_helpers branch from 842a214 to d7cd951 Compare May 21, 2026 16:08
@graphite-app graphite-app Bot merged commit d7cd951 into main May 21, 2026
30 checks passed
@graphite-app graphite-app Bot removed the 0-merge Merge with Graphite Merge Queue label May 21, 2026
@graphite-app graphite-app Bot deleted the 11-04-perf_parser_fast_path_identifier_kind_and_inline_operator_helpers branch May 21, 2026 16:12
Dunqing added a commit that referenced this pull request May 26, 2026
### 🚀 Features

- e857b0c napi/minify: Expose legalComments option and result (#20370)
(Boshen)
- 661132d parser: More friendly error messages for rest assignment
target and rest binding element (#22719) (sapphi-red)
- ee659b6 transformer/legacy-decorator: Add `strictNullChecks` option
for nullable-union design:type (#22266) (Kyle Cannon)

### 🐛 Bug Fixes

- e1d064e transformer/class-properties: Reparent lifted private method
helpers (#22716) (Cameron)
- 4ac0fca minifier: Preserve `0 && (module.exports = { ... })`
cjs-module-lexer hint (#22729) (Dunqing)
- 40ff611 minifier: Mark peephole loop changed when dropping
dead-after-throw statement (#22722) (Dunqing)
- 2f7b210 codegen: Emit pife-arrow/function leading comments inside the
wrap (#22720) (Dunqing)
- e184f74 parser: Improve invalid `import` property access diagnostic
(#22693) (camc314)
- 7baed9c transformer/private-method: Clear inherited strict flags
(#22508) (camc314)
- a9ad27e parser: Keep annotation comments leading without preceding
newline (#22711) (Dunqing)
- 9ea4d64 minifier: Re-evaluate pure/no-side-effects flags after
peephole inlining (#22595) (Dunqing)
- 07afbb6 minifier: Drop empty-body IIFE wrapper when called with
arguments (#22589) (Dunqing)
- fa7c463 semantic: Correct TS enum member symbol spans (#22689)
(camc314)
- 26b9396 semantic: Resolve parameter decorators outside parameter scope
(#22623) (camc314)
- b284045 parser: Switch to module goal eagerly on `export` (#22684)
(Boshen)
- dfa931d semantic: Propagate unresolved auto-increment enum value
instead of defaulting to 0 (#22646) (Dunqing)
- 69a6ba6 transformer/legacy-decorator: Emit Array for ReadonlyArray<T>
in decorator metadata (#22265) (Kyle Cannon)
- e421ef0 transformer/legacy-decorator: Return runtime binding for
design:type (#22640) (Dunqing)
- d61e1d7 codegen: Preserve verbatim text of pure/no-side-effects
comments (#22525) (Dunqing)
- 702b14e minifier: Preserve IIFE structure in DCE-only mode (#22547)
(Dunqing)
- 917da24 parser: Apply PURE comment through member-access chains
(#22566) (Dunqing)
- a069b1c codegen: Preserve quotes for cjs-module-lexer equality strings
(#22551) (Dunqing)

### ⚡ Performance

- 2f623b0 semantic: Skip unresolved checks for re-exports (#22660)
(camc314)
- 0d9553d semantic: Early-exit `check_object_expression` for objects
with <2 properties (#22668) (Dunqing)
- d721ad9 semantic: Use direct grandparent lookup for TS type parameters
(#22658) (camc314)
- 0aff288 semantic: Reorder numeric literal strict mode checks (#22657)
(camc314)
- 4d5ddb1 semantic: Reorder binding identifier checks (#22656) (camc314)
- e32acd8 semantic: Reorder identifier ambient binding check (#22653)
(camc314)
- 09fe178 semantic: Reorder ident reference strict mode check (#22652)
(camc314)
- 4b6add2 semantic: Avoid duplicate ident clone for bindings (#22663)
(camc314)
- 82f9662 parser: Check identifier kind before context flag (#22662)
(camc314)
- d7cd951 parser: Fast path identifier parsing and inline operator
helpers (#22650) (Boshen)
- 7b84314 semantic: Use direct byte access for numeric leading-zero
check (#22642) (camc314)
- 0345a31 semantic: Pre-size class elements hash map (#22618) (camc314)
- 04d3065 minifier: Drop per-call buffers in try_fold_concat (#22596)
(Dunqing)
- 4f289f1 semantic: Resolve_references_for_current_scope without a temp
Vec (#22599) (Dunqing)
- e862c15 semantic: Avoid heap alloc for var hoist scope ids (#22603)
(Dunqing)
- 8ff8674 semantic: Early return if `excess` is `0` in
`Stats::increase_by` (#22616) (camc314)
- 7a4120e semantic: Pre-reserve unresolved_references using
Stats::references (#22580) (Dunqing)

Co-authored-by: Dunqing <29533304+Dunqing@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-parser Area - Parser

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant