perf(serialization): reduce allocations in binary middleware hot paths - #21526
Conversation
Fold _deserialize's section accumulation into the read loop so a single-section stream no longer allocates an intermediate parts array or makes a second pass; use an indexed loop for the full-array buffer null-out to drop an iterator allocation.
🦋 Changeset detectedLatest commit: 43e6849 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
PR SummaryLow Risk Overview
Serialize flush when nulling buffer slots in the in-place path uses an indexed Changeset: patch note for reduced allocations on binary serialization hot paths. Reviewed by Cursor Bugbot for commit 43e6849. Bugbot is set up for automated code reviews on this repo. Configure here. |
|
This PR is packaged and the instant preview is available (aa1e746). Install it locally:
npm i -D webpack@https://pkg.pr.new/webpack@aa1e746
yarn add -D webpack@https://pkg.pr.new/webpack@aa1e746
pnpm add -D webpack@https://pkg.pr.new/webpack@aa1e746 |
Types CoverageCoverage after merging perf/binary-middleware-followup into main will be
Coverage Report |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #21526 +/- ##
==========================================
+ Coverage 93.78% 93.79% +0.01%
==========================================
Files 620 620
Lines 73371 73370 -1
Branches 21192 21196 +4
==========================================
+ Hits 68811 68818 +7
+ Misses 4560 4552 -8
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Merging this PR will regress 1 benchmark
|
| Mode | Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|---|
| ❌ | Memory | benchmark "asset-modules-resource", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' |
635.8 KB | 1,209.3 KB | -47.42% |
| ⚡ | Memory | benchmark "future-defaults", scenario '{"name":"mode-production","mode":"production"}' |
10.6 MB | 7.7 MB | +37.54% |
| ⚡ | Memory | benchmark "many-chunks-commonjs", scenario '{"name":"mode-production","mode":"production"}' |
8.5 MB | 7 MB | +21.72% |
| ⚡ | Simulation | benchmark "cache-filesystem", scenario '{"name":"mode-development","mode":"development"}' |
1.3 s | 1.1 s | +20.58% |
Tip
Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.
Comparing perf/binary-middleware-followup (43e6849) with main (84d351c)1
Footnotes
|
On the CodSpeed memory regression (
I read this as environment/base-substitution noise rather than a regression introduced here, so I don't plan to change the code for it. Happy to re-trigger the benchmark or acknowledge it on CodSpeed if preferred. Generated by Claude Code |
|
The The failing suites are I'll re-trigger the Bun job to clear the flake; I'm not changing the diff for it. If it reproduces, it's a pre-existing Bun/ Generated by Claude Code |
Summary
Follow-up to the V8 serializer rewrite (#21514). That path is bound by native
v8.serialize/v8.deserialize(benchmarking shows ~99% of deserialize is the native call and the JS framing is <1%), so this is not a wall-clock change — it just trims avoidable allocations on the hot path, in the spirit of #21516._deserializeallocated an intermediatepartsarray and made a second concatenation pass even for the dominant single-section stream; it now folds accumulation into the read loop (the first section's array becomes the result, later sections append in place). The full-array buffer null-out also switches from afor…ofiterator to an indexed loop to match the restore loop beside it. No behavior change. Refs #21514.What kind of change does this PR introduce?
perf
Did you add tests for your changes?
No — there is no behavior change; the existing
test/BinaryMiddleware.unittest.jsround-trip suite already covers the single-section, multi-section split, lazy, and frozen/buffer paths this touches.Does this PR introduce a breaking change?
No.
If relevant, what needs to be documented once your changes are merged or what have you already documented?
n/a
Use of AI
AI (Claude) was used to analyze the merged #21514 serializer for memory/performance, benchmark it (isolating native V8 cost from JS framing), and implement these allocation-hygiene cleanups; all changes were reviewed before submission.
Generated by Claude Code