Draft
Conversation
e3ab097 to
6cf2375
Compare
V8 uses a safepoint table to track which stack entries contain references. For each function, all safepoint entries share the same size, which must accommodate the stack at its deepest point. Large functions that allocate large arrays via `array.new_fixed` can cause the safepoint table to grow excessively, since each element requires a stack slot during initialization. This change introduces a threshold above which `array.new` is used instead, avoiding the stack pressure from inline element initialization.
6cf2375 to
1cb4359
Compare
|
FYI, It would be very interesting to repeat the measurements with a Chrome build that contains this commit, i.e. the 147.0.7687.0 Canary or later. Hopefully this workaround is then no longer necessary. |
Member
Author
@jakobkummerow Indeed, this makes a huge difference! Before:
After:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
V8 uses a safepoint table to track which stack entries contain GC references. For each function, all safepoint entries share the same size, which must accommodate the stack at its deepest point.
When using
array.new_fixed, each array element requires a stack slot during initialization. Large arrays cause excessive safepoint table growth.I have made some measurement on PRT (partial render table benchmark). For this program, a single 6913-element array (a parser transition table) caused the safepoint table to balloon to 8.5 MB.
Solution
Introduce a size threshold above which
array.new+ explicit stores is used instead ofarray.new_fixed. This avoids stack pressure from inline element initialization.Current threshold: 100 elements
Measurements (PRT benchmark)
Key observations
array.new_fixed, the stack has more constant depth, leading to more deduplicationarray.new_fixedcalls, which compound stack depth (inner arrays remain on the stack while outer arrays are initialized)Array Size Distribution
Analysis of ~36,500 array allocations in the test program:
The distribution is heavily skewed toward small arrays. Only ~1% of arrays exceed size 63, and only ~25 arrays exceed size 100.
There is a gap between sizes 137 and 257 in this program, meaning the difference between threshold 100 and 200 is smaller than it might be for other programs.
Threshold Choice
The current threshold of 100 is reasonable. A lower threshold (64) would provide additional safety margin for programs with different distributions, but the benefit is marginal given how skewed the distribution is toward small arrays.
Notes
node --print-wasm-codeentries × ceil(stack_slots / 8)