perf: build the binary deserialize dispatch table once instead of per call#21175
Conversation
… call BinaryMiddleware._deserialize rebuilt a 256-entry table of closures on every call, and warm persistent-cache restores call it once per lazy section. Hoist the table to module scope operating on a small per-call ReadState, and read section lengths without allocating a temporary buffer per u32. ~20x faster on a many-small-sections microbenchmark. https://claude.ai/code/session_01DLut6MuNBwztSkZUCvmfvW
🦋 Changeset detectedLatest commit: 10cf831 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 |
|
This PR is packaged and the instant preview is available (8574c92). Install it locally:
npm i -D webpack@https://pkg.pr.new/webpack@8574c92
yarn add -D webpack@https://pkg.pr.new/webpack@8574c92
pnpm add -D webpack@https://pkg.pr.new/webpack@8574c92 |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #21175 +/- ##
==========================================
+ Coverage 92.60% 92.67% +0.07%
==========================================
Files 586 586
Lines 63823 63827 +4
Branches 17691 17690 -1
==========================================
+ Hits 59101 59150 +49
+ Misses 4722 4677 -45
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 improve performance by 34.71%
|
| Mode | Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|---|
| ❌ | Memory | benchmark "asset-modules-inline", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' |
324 KB | 1,298.8 KB | -75.05% |
| ⚡ | Memory | benchmark "lodash", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' |
858.1 KB | 126.1 KB | ×6.8 |
| ⚡ | Memory | benchmark "side-effects-reexport", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' |
1,196.8 KB | 760.7 KB | +57.34% |
| ⚡ | Memory | benchmark "devtool-eval-source-map", scenario '{"name":"mode-production","mode":"production"}' |
8 MB | 6.5 MB | +23.32% |
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-dispatch-table (10cf831) with main (2a74860)
|
Note on the CodSpeed-flagged Generated by Claude Code |
Summary
BinaryMiddleware._deserializerebuilt a 256-entry closure dispatch table on every call, which is hot during filesystem-cache restores: incremental rebuilds that force per-module source sections (e.g. withdevtool: "source-map") pay it once per module. Hoisting the table to module scope (handlers operating on a smallReadState) plus areadU32fast path makes binary decode ~37% faster and removes ~116 MB of allocation churn per incremental rebuild on a 3k-module benchmark (~4% whole-rebuild wall time).What kind of change does this PR introduce?
perf
Did you add tests for your changes?
No new tests; the decode logic is translated 1:1 and covered by the exhaustive round-trip suite in
test/BinaryMiddleware.unittest.js(18k cases) andtest/TestCasesCachePack.longtest.js.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
Implemented and benchmarked with Claude Code (AI assistant) under the author's direction; the author reviewed the change and the verification results.
Generated by Claude Code