Skip to content

perf(semantic): mark checker::check as inline(always)#17459

Merged
graphite-app[bot] merged 1 commit intomainfrom
c/12-29-perf_semantic_test
Dec 30, 2025
Merged

perf(semantic): mark checker::check as inline(always)#17459
graphite-app[bot] merged 1 commit intomainfrom
c/12-29-perf_semantic_test

Conversation

@camc314
Copy link
Contributor

@camc314 camc314 commented Dec 29, 2025

the reasoning here is:

  1. check is a big function with a big match arm
  2. if we inline it into leave_node
  3. and inline leave_node into it's caller
  4. the match will be flattened, as the compiler knows what varient of the kind it is, this means all the other match arms can be dropped, as well as the match it's self, just leaving the call into the check fn (if needed) <- if this works correctly, it also means this change will hardly have any impact on binary size

@github-actions github-actions bot added A-semantic Area - Semantic C-performance Category - Solution not expected to change functional behavior, only performance labels Dec 29, 2025
Copy link
Contributor Author

camc314 commented Dec 29, 2025


How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • 0-merge - adds this PR to the back of the merge queue
  • hotfix - for urgent hot fixes, skip the queue and merge this PR next

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@codspeed-hq
Copy link

codspeed-hq bot commented Dec 29, 2025

CodSpeed Performance Report

Merging #17459 will improve performance by 10.13%

Comparing c/12-29-perf_semantic_test (f448e31) with main (68b2e54)

Summary

⚡ 4 improvements
✅ 38 untouched
⏩ 3 skipped1

Benchmarks breakdown

Mode Benchmark BASE HEAD Efficiency
Simulation semantic[binder.ts] 4 ms 3.7 ms +6.45%
Simulation semantic[RadixUIAdoptionSection.jsx] 74 µs 67.2 µs +10.13%
Simulation semantic[cal.com.tsx] 25.8 ms 23.9 ms +7.97%
Simulation semantic[react.development.js] 1.6 ms 1.5 ms +6.34%

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.

Copy link
Member

@Boshen Boshen left a comment

Choose a reason for hiding this comment

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

Add two inline comments to these two #[inline(always)] and we should be good to go!

@camc314 camc314 changed the title perf(semantic): test perf(semantic): mark checker::check as inline(always) Dec 30, 2025
@camc314 camc314 force-pushed the c/12-29-perf_semantic_test branch from 8d811b5 to 91383cc Compare December 30, 2025 10:57
@camc314 camc314 marked this pull request as ready for review December 30, 2025 10:57
@camc314 camc314 requested a review from Dunqing as a code owner December 30, 2025 10:57
Copilot AI review requested due to automatic review settings December 30, 2025 10:57
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR applies a performance optimization by marking two functions with #[inline(always)] to enable compile-time match arm elimination. The strategy relies on inlining both checker::check and SemanticBuilder::leave_node so that when each visit_* method calls leave_node with a statically known AstKind variant, the compiler can constant-fold the large match statement in checker::check, eliminating all non-matching arms and reducing both execution time and potentially binary size.

  • Adds #[inline(always)] to checker::check with comprehensive documentation
  • Adds #[inline(always)] to SemanticBuilder::leave_node with explanatory comments
  • Both use #[expect(clippy::inline_always)] with clear reasoning for the optimization

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
crates/oxc_semantic/src/checker/mod.rs Adds documentation and #[inline(always)] attribute to the check function to enable compile-time match elimination
crates/oxc_semantic/src/builder.rs Adds documentation and #[inline(always)] attribute to the leave_node method to complete the inlining chain

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@camc314 camc314 force-pushed the c/12-29-perf_semantic_test branch from b53f449 to f448e31 Compare December 30, 2025 10:59
@graphite-app graphite-app bot added the 0-merge Merge with Graphite Merge Queue label Dec 30, 2025
@graphite-app
Copy link
Contributor

graphite-app bot commented Dec 30, 2025

Merge activity

the reasoning here is:
1. `check` is a big function with a big match arm
2. if we inline it into leave_node
3. and inline leave_node into it's caller
4. the match will be flattened, as the compiler knows what varient of the kind it is, this means all the other match arms can be dropped, as well as the match it's self, just leaving the call into the check fn (if needed) <- if this works correctly, it also means this change will hardly have any impact on binary size
@graphite-app graphite-app bot force-pushed the c/12-29-perf_semantic_test branch from f448e31 to d968e51 Compare December 30, 2025 11:40
@graphite-app graphite-app bot merged commit d968e51 into main Dec 30, 2025
20 checks passed
@graphite-app graphite-app bot deleted the c/12-29-perf_semantic_test branch December 30, 2025 11:46
@graphite-app graphite-app bot removed the 0-merge Merge with Graphite Merge Queue label Dec 30, 2025
graphite-app bot pushed a commit that referenced this pull request Jan 5, 2026
### 🚀 Features

- 659c23e linter: Init note field boilerplate  (#17589) (Shrey Sudhir)
- 6870b64 parser: Add TS1363 error code (#17609) (Sysix)
- 23680a3 mangler: Skip mangling only in scopes affected by direct eval (#17612) (camc314)
- a7e1643 parser: Add TS2528 error code to duplicate_default_export diagnostic (#17558) (camc314)

### 🐛 Bug Fixes

- 1044116 ecmascript: Mark `new Symbol` as non side-effect free (#17568) (camc314)
- ab5e4ca isolated-declarations: Strip default values from rest parameter binding patterns (#17602) (camc314)
- 68b2e54 minifier: Prevent incorrect ??= transformation when member base is mutated (#17472) (copilot-swe-agent)

### ⚡ Performance

- 6067143 semantic: Remove hash when checking identifier (#17564) (camchenry)
- a28ab3d semantic: Avoid bounds check when checking string literal (#17545) (camc314)
- 04809d1 semantic: Use SIMD for finding backslashes in `check_string_literal` (#17534) (camchenry)
- 49ad2f0 semantic: Mark all diagnostic functions as `#[cold]` (#17487) (camc314)
- ea82b50 transformer: Mark all diagnostic functions as `#[cold]` (#17486) (camc314)
- d968e51 semantic: Mark `checker::check` as `inline(always)` (#17459) (camc314)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-semantic Area - Semantic C-performance Category - Solution not expected to change functional behavior, only performance

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants