heap: auto near oom headroom extension - #401
Conversation
Overall package sizeSelf size: 2.55 MB Dependency sizes| name | version | self size | total size | |------|---------|-----------|------------| | pprof-format | 2.3.1 | 504.33 kB | 504.33 kB | | source-map | 0.8.0 | 185.66 kB | 185.66 kB | | node-gyp-build | 4.8.4 | 13.86 kB | 13.86 kB |🤖 This report was automatically generated by heaviest-objects-in-the-universe |
szegedi
left a comment
There was a problem hiding this comment.
Looks good overall, I have one small question to better understand it, tho'
|
|
||
| size_t extension = state->heap_extension_size; | ||
| if (state->automatic_heap_extension) { | ||
| if (!state->automatic_heap_extension_size.has_value()) { |
There was a problem hiding this comment.
So automatic_heap_extension_size is computed once, and then reused next time. I guess what I'm asking is why is the total_heap_limit - current_heap_limit value computed the first time valid for subsequent times?
There was a problem hiding this comment.
The diff is the young generation size and It's reusable because the old generation limit is in both terms and cancels, and the young generation is fixed once at isolate startup.
|
I changed this to "semver-minor" as it introduces new backwards-compatible functionality. |
|
@nsavoire Can you please take a look? Asking because I believe you're the author of this |
Current behaviour
When V8 signals it is near the heap limit, the callback:
heapLimitExtensionSizeThe problem is step 1. That number is a constant and nothing ties it to what V8 actually needs to finish one more GC while we capture. When it is too small the allocation still isn't satisfied, so V8 calls us again, and every one of those calls redoes the whole thing: heap stats, GetAllocationProfile(), translation, another spawned process. Repetitive work, and each round burns the extension budget for nothing.
That is also why the default kept creeping up (10 MiB, then 20 MiB) without any real basis.
Meanwhile V8 already reserves headroom beyond the old generation and will happily tell us how much. Why guess a constant instead of using what is already there?
Proposed solution
Inspired by how Node.js sizes its own near-OOM heap snapshot which extends by one young generation rather than a constant.
heapLimitExtensionSizenow also accepts'auto', and when set:heap_size_limit()current_heap_limit, which is exactly one maximum young generation and cache it for later events.This is not a breaking change. Numeric sizes behave exactly as before, including 0 meaning "grant nothing", and the constant reentrant rescue that lets an in-progress capture finish. 'auto' is opt-in.