perf(linter/plugins): use SoA pattern with 2 arrays for CFG steps#18528
perf(linter/plugins): use SoA pattern with 2 arrays for CFG steps#18528overlookmotel merged 7 commits intooxc-project:mainfrom
Conversation
There was a problem hiding this comment.
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
stepsarray with two SoA arrays:stepTypeIdsfor encoded type IDs andstepDatafor nodes or arguments - Introduced type ID encoding using
EXIT_TYPE_ID_OFFSETto distinguish enter visits, CFG events, and exit visits - Removed dependency on
@eslint/plugin-kitpackage
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.
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.
6035bbc to
687d45d
Compare
overlookmotel
left a comment
There was a problem hiding this comment.
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.
…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>
Part 2 of #17232, continuing after #18527 - CFG walker optimization.
stepsarray with 2 SoA (Struct of Arrays):stepTypeIds: encoded type IDsstepData: node or args arrayBenefits:
NODE_TYPE_IDS_MAPhash map lookups to convert node types (strings) to type IDs.