From 6d06ac22027337f915fb54c7338b13ec2c6d3c9f Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Thu, 22 Oct 2020 03:41:11 +0800 Subject: [PATCH] src: add --heapsnapshot-near-heap-limit option This patch adds a --heapsnapshot-near-heap-limit CLI option that takes heap snapshots when the V8 heap is approaching the heap size limit. It will try to write the snapshots to disk before the program crashes due to OOM. PR-URL: https://github.com/nodejs/node/pull/33010 Refs: https://github.com/nodejs/node/issues/27552 Reviewed-By: Anna Henningsen Reviewed-By: Richard Lau Reviewed-By: Gireesh Punathil --- doc/api/cli.md | 47 ++++++ doc/node.1 | 4 + src/debug_utils.h | 1 + src/env-inl.h | 16 ++ src/env.cc | 146 ++++++++++++++++++ src/env.h | 10 ++ src/heap_utils.cc | 6 +- src/inspector_profiler.cc | 20 +-- src/node.cc | 4 + src/node_internals.h | 4 + src/node_main_instance.cc | 2 + src/node_options.cc | 10 ++ src/node_options.h | 1 + src/node_worker.cc | 5 + test/fixtures/workload/bounded.js | 22 +++ test/fixtures/workload/grow-worker.js | 14 ++ test/fixtures/workload/grow.js | 12 ++ ...st-heapsnapshot-near-heap-limit-bounded.js | 36 +++++ .../test-heapsnapshot-near-heap-limit.js | 114 ++++++++++++++ .../test-heapsnapshot-near-heap-limit-big.js | 43 ++++++ 20 files changed, 496 insertions(+), 21 deletions(-) create mode 100644 test/fixtures/workload/bounded.js create mode 100644 test/fixtures/workload/grow-worker.js create mode 100644 test/fixtures/workload/grow.js create mode 100644 test/parallel/test-heapsnapshot-near-heap-limit-bounded.js create mode 100644 test/parallel/test-heapsnapshot-near-heap-limit.js create mode 100644 test/pummel/test-heapsnapshot-near-heap-limit-big.js diff --git a/doc/api/cli.md b/doc/api/cli.md index 2ee780d4b0ba75..1b3bdf4484f757 100644 --- a/doc/api/cli.md +++ b/doc/api/cli.md @@ -337,6 +337,52 @@ reference. Code may break under this flag. `--require` runs prior to freezing intrinsics in order to allow polyfills to be added. +### `--heapsnapshot-near-heap-limit=max_count` + + +> Stability: 1 - Experimental + +Writes a V8 heap snapshot to disk when the V8 heap usage is approaching the +heap limit. `count` should be a non-negative integer (in which case +Node.js will write no more than `max_count` snapshots to disk). + +When generating snapshots, garbage collection may be triggered and bring +the heap usage down, therefore multiple snapshots may be written to disk +before the Node.js instance finally runs out of memory. These heap snapshots +can be compared to determine what objects are being allocated during the +time consecutive snapshots are taken. It's not guaranteed that Node.js will +write exactly `max_count` snapshots to disk, but it will try +its best to generate at least one and up to `max_count` snapshots before the +Node.js instance runs out of memory when `max_count` is greater than `0`. + +Generating V8 snapshots takes time and memory (both memory managed by the +V8 heap and native memory outside the V8 heap). The bigger the heap is, +the more resources it needs. Node.js will adjust the V8 heap to accommondate +the additional V8 heap memory overhead, and try its best to avoid using up +all the memory avialable to the process. When the process uses +more memory than the system deems appropriate, the process may be terminated +abruptly by the system, depending on the system configuration. + +```console +$ node --max-old-space-size=100 --heapsnapshot-near-heap-limit=3 index.js +Wrote snapshot to Heap.20200430.100036.49580.0.001.heapsnapshot +Wrote snapshot to Heap.20200430.100037.49580.0.002.heapsnapshot +Wrote snapshot to Heap.20200430.100038.49580.0.003.heapsnapshot + +<--- Last few GCs ---> + +[49580:0x110000000] 4826 ms: Mark-sweep 130.6 (147.8) -> 130.5 (147.8) MB, 27.4 / 0.0 ms (average mu = 0.126, current mu = 0.034) allocation failure scavenge might not succeed +[49580:0x110000000] 4845 ms: Mark-sweep 130.6 (147.8) -> 130.6 (147.8) MB, 18.8 / 0.0 ms (average mu = 0.088, current mu = 0.031) allocation failure scavenge might not succeed + + +<--- JS stacktrace ---> + +FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory +.... +``` + ### `--heapsnapshot-signal=signal`