Skip to content

perf(diagnostics): box OxcDiagnosticInner to reduce binary size by 4%#24656

Closed
Boshen wants to merge 1 commit into
perf/defer-parser-diagnosticsfrom
perf/box-oxc-diagnostic-inner
Closed

perf(diagnostics): box OxcDiagnosticInner to reduce binary size by 4%#24656
Boshen wants to merge 1 commit into
perf/defer-parser-diagnosticsfrom
perf/box-oxc-diagnostic-inner

Conversation

@Boshen

@Boshen Boshen commented Jul 19, 2026

Copy link
Copy Markdown
Member

OxcDiagnostic is an unboxed ~304-byte struct constructed at thousands of
callsites. Boxing its inner data behind an 8-byte handle shrinks the stripped
oxlint release binary by ~549 KiB (-4.0%): oxc_linter -307 KiB,
oxc_react_compiler -102 KiB, and others.

This reverses #22406, which unboxed the inner to save a heap allocation. That is
now safe: the parser no longer constructs diagnostics on its hot path (see the
previous commit). Also drops the now-obsolete large_enum_variant expectation
on CliConfigLoadError, whose OxcDiagnostic variant is now small.


Stack created with GitHub Stacks CLIGive Feedback 💬

`OxcDiagnostic` is an unboxed ~304-byte struct constructed at thousands of
callsites. Boxing its inner data behind an 8-byte handle shrinks the stripped
`oxlint` release binary by ~549 KiB (-4.0%): oxc_linter -307 KiB,
oxc_react_compiler -102 KiB, and others.

This reverses #22406, which unboxed the inner to save a heap allocation. That is
now safe: the parser no longer constructs diagnostics on its hot path (see the
previous commit). Also drops the now-obsolete `large_enum_variant` expectation
on `CliConfigLoadError`, whose `OxcDiagnostic` variant is now small.
@codspeed-hq

codspeed-hq Bot commented Jul 19, 2026

Copy link
Copy Markdown

Merging this PR will improve performance by 5.55%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 7 improved benchmarks
✅ 60 untouched benchmarks
⏩ 9 skipped benchmarks1

Performance Changes

Mode Benchmark BASE HEAD Efficiency
Simulation react_compiler[RadixUIAdoptionSection.jsx] 2.7 ms 2.5 ms +7.6%
Simulation linter[react.development.js] 13.6 ms 12.7 ms +7.37%
Simulation linter[RadixUIAdoptionSection.jsx] 3.2 ms 3 ms +7.21%
Simulation linter[binder.ts] 27 ms 25.8 ms +4.94%
Simulation parser[RadixUIAdoptionSection.jsx] 84.8 µs 80.9 µs +4.83%
Simulation linter[App.tsx] 67.7 ms 65 ms +4%
Simulation transformer[react.development.js] 705.5 µs 684.9 µs +3.01%

Tip

Curious why this is faster? Comment @codspeedbot explain why this is faster on this PR, or directly use the CodSpeed MCP with your agent.


Comparing perf/box-oxc-diagnostic-inner (3975763) with perf/defer-parser-diagnostics (8ce3853)

Open in CodSpeed

Footnotes

  1. 9 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 marked this pull request as draft July 19, 2026 06:21
graphite-app Bot pushed a commit that referenced this pull request Jul 19, 2026
`OxcDiagnostic` is an unboxed ~300-byte struct constructed at thousands of callsites. Boxing its inner data behind an 8-byte handle means every callsite, every `Result<T, OxcDiagnostic>`, and every move copies 8 bytes instead of ~300, so the compiler emits far less inlined construction/copy code.

## Binary size (stripped, real release builds, aarch64-apple-darwin)

| Binary | Before | After | Delta |
|---|---:|---:|---:|
| `oxlint` | 14,177,616 B | 13,665,680 B | **−499.9 KiB (−3.61%)** |
| napi transform (`.node`) | 3,482,624 B | 3,433,040 B | **−48.4 KiB (−1.42%)** |

Most of the win lands in `oxc_linter`, whose ~1,500 diagnostic-construction sites inline into rule bodies; `oxc_react_compiler` also contributes.

The `error`/`warn` constructors delegate to an outlined `#[inline(never)] fn new`, so the `Box` allocation + field initialization exist once in the binary rather than inlined at every construction site.

This reverses #22406, which unboxed the inner to save a heap allocation. That is now safe: the parser no longer constructs diagnostics on its hot path (#24663).

Supersedes the draft #24656, which additionally carried a now-redundant copy of the parser deferral that has since landed via #24663.
@Boshen Boshen closed this Jul 19, 2026
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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant