Skip to content

perf(linter/plugins): use SoA pattern with 2 arrays for CFG steps#18528

Merged
overlookmotel merged 7 commits intooxc-project:mainfrom
re-taro:refactor/cfg-step2-soa
Jan 26, 2026
Merged

perf(linter/plugins): use SoA pattern with 2 arrays for CFG steps#18528
overlookmotel merged 7 commits intooxc-project:mainfrom
re-taro:refactor/cfg-step2-soa

Conversation

@re-taro
Copy link
Contributor

@re-taro re-taro commented Jan 25, 2026

Part 2 of #17232, continuing after #18527 - CFG walker optimization.

  • Replace single steps array with 2 SoA (Struct of Arrays):
    • stepTypeIds: encoded type IDs
    • stepData: node or args array
  • Encode step types using type ID offset:
    • Enter visits: typeId directly (0-164 for node types)
    • CFG events: typeId directly (165-171 for event types)
    • Exit visits: typeId + 256 (offset to distinguish from enter)
  • Pre-compute type IDs during step preparation phase

Benefits:

  • Reduces object creation overhead (no step objects needed).
  • Halves the number of NODE_TYPE_IDS_MAP hash map lookups to convert node types (strings) to type IDs.

Copilot AI review requested due to automatic review settings January 25, 2026 16:14
@github-actions github-actions bot added A-linter Area - Linter A-cli Area - CLI A-linter-plugins Area - Linter JS plugins C-performance Category - Solution not expected to change functional behavior, only performance labels Jan 25, 2026
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 optimizes the CFG (Control Flow Graph) walker by replacing an array of step objects with a Struct of Arrays (SoA) pattern using two separate arrays, improving memory locality and reducing object creation overhead.

Changes:

  • Replaced the steps array with two SoA arrays: stepTypeIds for encoded type IDs and stepData for nodes or arguments
  • Introduced type ID encoding using EXIT_TYPE_ID_OFFSET to distinguish enter visits, CFG events, and exit visits
  • Removed dependency on @eslint/plugin-kit package

Reviewed changes

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

File Description
apps/oxlint/src-js/plugins/cfg.ts Implements SoA pattern with stepTypeIds and stepData arrays, adds type ID encoding logic, and updates step preparation and execution
apps/oxlint/package.json Removes unused @eslint/plugin-kit dependency
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

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

re-taro and others added 7 commits January 26, 2026 14:13
This is Part 1 of CFG walker optimization series addressing TODO comments
in cfg.ts.

Changes:
- Remove `@eslint/plugin-kit` dependency (no longer needed)
- Replace `VisitNodeStep` and `CallMethodStep` classes with plain objects
- Merge `kind` and `phase` into a single `type` property:
  - 0 = enter visit
  - 1 = exit visit
  - 2 = call method (CFG event)

This reduces object creation overhead and improves memory efficiency
by using simpler data structures.

perf(js-plugins): use SoA pattern with 2 arrays for CFG steps

This is Part 2 of CFG walker optimization series.

Changes:
- Replace single `steps` array with 2 SoA (Struct of Arrays):
  - `stepTypeIds`: encoded type IDs
  - `stepData`: node or args array
- Encode step types using type ID offset:
  - Enter visits: typeId directly (0-164 for node types)
  - CFG events: typeId directly (165-171 for event types)
  - Exit visits: typeId + 256 (offset to distinguish from enter)
- Pre-compute type IDs during step preparation phase

Benefits:
- Reduces object creation overhead (no step objects needed)
- Improves memory locality (contiguous arrays)
- Avoids repeated string-to-number type conversions during execution

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Most often taken branches first.
@overlookmotel overlookmotel force-pushed the refactor/cfg-step2-soa branch from 6035bbc to 687d45d Compare January 26, 2026 14:14
Copy link
Member

@overlookmotel overlookmotel left a comment

Choose a reason for hiding this comment

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

Thank you.

As I mentioned on #18527, I'm keen to get this merged ASAP, so I've taken the liberty of pushing some commits instead of making review comments and waiting for you to have time to address them.

All minor things though - I've not altered the underlying logic of this PR at all.

@overlookmotel overlookmotel self-assigned this Jan 26, 2026
@overlookmotel overlookmotel changed the title perf(js-plugins): use SoA pattern with 2 arrays for CFG steps perf(linter/plugins): use SoA pattern with 2 arrays for CFG steps Jan 26, 2026
@overlookmotel overlookmotel merged commit 2b9d115 into oxc-project:main Jan 26, 2026
20 checks passed
@re-taro re-taro deleted the refactor/cfg-step2-soa branch January 26, 2026 15:06
overlookmotel added a commit that referenced this pull request Jan 26, 2026
…rseNode (#18529)

Part 3 of #17232, continuing after #18527 and #18528 - CFG walker
optimization.

- Remove ESLint's `Traverser`
- Add lightweight `traverseNode` function that walks AST using visitor
keys
- Simplify traversal by only calling enter/leave callbacks without extra
overhead

Benefits:

- Eliminates ESLint Traverser overhead (ancestors tracking, etc.)
- Uses pre-generated visitor keys for child property lookup
- Reduces bundle size by removing unused ESLint internal module (~1.7KB
smaller)

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: overlookmotel <theoverlookmotel@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-cli Area - CLI A-linter Area - Linter A-linter-plugins Area - Linter JS plugins 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.

2 participants