Commit ed1c6cc
perf(ecmascript): shrink JsValue 64→32 bytes (vercel#93106)
Three changes that together shrink `JsValue` from **64 → 32 bytes**
(−50%). JsValue is the analyzer's value type and is instantiated
millions of times during large-app analysis, so this directly reduces
peak memory and improves cache locality on the hot
`link`/`replace_builtin` paths.
## Changes
### 1. Box `RequireContextValue` inside `WellKnownFunctionKind`
`RequireContextValue` carries an `FxIndexMap` and is only used by three
variants (`RequireContextRequire{,Keys,Resolve}`). Boxing it pulls those
variants' payload down from 48B to 8B, dropping `WellKnownFunctionKind`
from 64 → 16 bytes and `JsValue` from 64 → 48 bytes.
### 2. Unify `MemberCall`/`New`/`Call` payload into a single `Vec`
`MemberCall` was `(u32, Box<JsValue>, Box<JsValue>, Vec<JsValue>)` (48B
payload). Collapsed into `(u32, Vec<JsValue>)` (24B payload) with
storage layout `[args..., prop, obj]`.
The reversed order is the key trick: on the common fallthrough in
`builtin::replace_builtin` (convert `obj.prop(args)` into a
`Call(Member(obj, prop), args)`), we pop `obj` then `prop` off the tail
of the Vec and reuse the remainder **as** the args Vec — zero extra
allocations on the hot path.
A similar optimization was applied to `New` and `Call`
A tricky think about this layout is avoiding reallocations of 'arg' vecs
when constructing, To make this easier I added parallel factory methods
`JsValue::call_from_parts` and `JsValue::call_from_iter` to eliminate
reallocations when constructing
Drops JsValue from 48 → 40 bytes.
### 3. Replace `Unknown::reason` with `RcStr`
The `reason` field of Unknown was a `Cow<&'static, str>` but nearly all
uses were `&'static str` values so they were migrated to `rcstr!` which
drops the reason field from 24 bytes to 8 bytes.
Drops JsValue from 40 -> 32 bytes
## Test plan
- [x] `cargo test -p turbopack-ecmascript --lib` — all 352 tests pass
(snapshot fixtures byte-identical)
## Benchmark results
Ran `cargo bench -p turbopack-ecmascript --bench analyzer` on this
branch vs `canary` (59 fixtures × 2 benches each, criterion baselines).
| Bench | Sum (canary → branch) | Δ | Geomean ratio |
|---|---|---|---|
| `link` | 72.26 ms → 66.41 ms | **−8.09%** | **−2.94%** |
| `create_graph` | 8.15 ms → 7.93 ms | **−2.60%** | **−2.95%** |
The biggest absolute wins are on `link`, the JsValue-heavy hot path
(linker walks every node, clones, hashes via `similar_hash`, compares
via `similar`).
**Notable wins on `link`:**
- `react-dom-production` **−5.70%** (38.40 ms → 36.21 ms — the largest
fixture, ~2 ms saved)
- `peg` **−11.39%** (25.65 ms → 22.72 ms)
- `cycle-cache` **−9.04%** (3.94 ms → 3.58 ms)
- `md5` **−19.19%** (1.09 ms → 879 µs)
- `md5-reduced` **−12.75%** (386 µs → 337 µs)
- `md5_2` **−11.33%** (783 µs → 694 µs)
**Notable wins on `create_graph`:**
- `webpack-target-node` **−8.30%**, `require-context` **−7.67%**, `peg`
**−5.53%**, `cycle-cache` **−4.36%**, `mongoose-reduced` **−6.49%**,
`process-and-os` **−6.11%**
**Regressions:** zero in `create_graph`. Three nominal "+1.5% to +3.5%"
outliers in `link` (`link/2`, `link/object`, `link/try`) all reproduce
as **−4% to −7% improvements** when re-run individually against canary —
they are run-to-run noise on small fixtures (criterion CI ≈ ±2-3%), not
real regressions. Every fixture above ~1 ms shows a clear improvement
consistently.
<!-- NEXT_JS_LLM_PR -->
---------
Co-authored-by: Luke Sandberg <lukesandberg@users.noreply.github.com>1 parent d55787f commit ed1c6cc
6 files changed
Lines changed: 978 additions & 648 deletions
File tree
- turbopack/crates/turbopack-ecmascript/src
- analyzer
- references
Lines changed: 59 additions & 47 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
| 3 | + | |
| 4 | + | |
3 | 5 | | |
4 | 6 | | |
5 | 7 | | |
| |||
9 | 11 | | |
10 | 12 | | |
11 | 13 | | |
12 | | - | |
| 14 | + | |
| 15 | + | |
13 | 16 | | |
14 | 17 | | |
15 | 18 | | |
| |||
19 | 22 | | |
20 | 23 | | |
21 | 24 | | |
22 | | - | |
| 25 | + | |
23 | 26 | | |
24 | 27 | | |
25 | 28 | | |
| |||
34 | 37 | | |
35 | 38 | | |
36 | 39 | | |
37 | | - | |
| 40 | + | |
38 | 41 | | |
39 | 42 | | |
40 | 43 | | |
41 | 44 | | |
42 | 45 | | |
43 | 46 | | |
44 | | - | |
| 47 | + | |
| 48 | + | |
45 | 49 | | |
46 | 50 | | |
47 | 51 | | |
| |||
52 | 56 | | |
53 | 57 | | |
54 | 58 | | |
55 | | - | |
| 59 | + | |
56 | 60 | | |
57 | 61 | | |
58 | 62 | | |
| |||
64 | 68 | | |
65 | 69 | | |
66 | 70 | | |
67 | | - | |
| 71 | + | |
68 | 72 | | |
69 | 73 | | |
70 | 74 | | |
| |||
83 | 87 | | |
84 | 88 | | |
85 | 89 | | |
86 | | - | |
| 90 | + | |
87 | 91 | | |
88 | 92 | | |
89 | 93 | | |
| |||
137 | 141 | | |
138 | 142 | | |
139 | 143 | | |
140 | | - | |
| 144 | + | |
141 | 145 | | |
142 | 146 | | |
143 | 147 | | |
| |||
156 | 160 | | |
157 | 161 | | |
158 | 162 | | |
159 | | - | |
| 163 | + | |
160 | 164 | | |
161 | 165 | | |
162 | 166 | | |
163 | 167 | | |
164 | | - | |
| 168 | + | |
165 | 169 | | |
166 | 170 | | |
167 | 171 | | |
168 | 172 | | |
169 | 173 | | |
170 | 174 | | |
171 | | - | |
| 175 | + | |
172 | 176 | | |
173 | 177 | | |
174 | 178 | | |
| |||
218 | 222 | | |
219 | 223 | | |
220 | 224 | | |
221 | | - | |
| 225 | + | |
222 | 226 | | |
223 | 227 | | |
224 | 228 | | |
| |||
230 | 234 | | |
231 | 235 | | |
232 | 236 | | |
233 | | - | |
| 237 | + | |
234 | 238 | | |
235 | 239 | | |
236 | 240 | | |
| |||
295 | 299 | | |
296 | 300 | | |
297 | 301 | | |
298 | | - | |
| 302 | + | |
299 | 303 | | |
300 | 304 | | |
301 | 305 | | |
| |||
338 | 342 | | |
339 | 343 | | |
340 | 344 | | |
341 | | - | |
342 | | - | |
343 | | - | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
344 | 351 | | |
345 | 352 | | |
346 | 353 | | |
| |||
368 | 375 | | |
369 | 376 | | |
370 | 377 | | |
371 | | - | |
372 | | - | |
| 378 | + | |
| 379 | + | |
373 | 380 | | |
374 | | - | |
| 381 | + | |
375 | 382 | | |
376 | 383 | | |
377 | 384 | | |
378 | 385 | | |
379 | 386 | | |
380 | | - | |
381 | | - | |
| 387 | + | |
| 388 | + | |
382 | 389 | | |
383 | 390 | | |
384 | 391 | | |
385 | 392 | | |
386 | 393 | | |
387 | 394 | | |
388 | 395 | | |
389 | | - | |
| 396 | + | |
390 | 397 | | |
391 | 398 | | |
392 | 399 | | |
| |||
397 | 404 | | |
398 | 405 | | |
399 | 406 | | |
400 | | - | |
401 | | - | |
402 | | - | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
403 | 410 | | |
404 | 411 | | |
405 | 412 | | |
| |||
427 | 434 | | |
428 | 435 | | |
429 | 436 | | |
430 | | - | |
431 | | - | |
432 | | - | |
433 | | - | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
434 | 441 | | |
435 | 442 | | |
436 | 443 | | |
| |||
446 | 453 | | |
447 | 454 | | |
448 | 455 | | |
449 | | - | |
450 | | - | |
| 456 | + | |
| 457 | + | |
451 | 458 | | |
452 | 459 | | |
453 | 460 | | |
454 | 461 | | |
455 | 462 | | |
456 | 463 | | |
457 | 464 | | |
458 | | - | |
459 | | - | |
460 | | - | |
461 | | - | |
| 465 | + | |
| 466 | + | |
| 467 | + | |
| 468 | + | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
| 474 | + | |
462 | 475 | | |
463 | 476 | | |
464 | 477 | | |
465 | 478 | | |
466 | 479 | | |
467 | | - | |
468 | | - | |
469 | | - | |
470 | | - | |
471 | | - | |
472 | | - | |
473 | | - | |
474 | | - | |
475 | | - | |
| 480 | + | |
| 481 | + | |
| 482 | + | |
| 483 | + | |
| 484 | + | |
| 485 | + | |
| 486 | + | |
| 487 | + | |
476 | 488 | | |
477 | | - | |
| 489 | + | |
478 | 490 | | |
479 | | - | |
| 491 | + | |
480 | 492 | | |
481 | 493 | | |
482 | 494 | | |
| |||
0 commit comments