How do I determine the correct "max-old-space-size" for Node.js?
Asked Answered
H

7

315

I'm having some trouble to understand how Node.js acts based on the parameter max-old-space-size.

In my case, for example, I'm running two t2.small AWS instances (2GB of RAM).

Not sure why, but I did set max-old-space-size=4096 (4GB). What does node do in this case? Could this configuration lead to a possible memory allocation failure?

How do I determine the correct value of max-old-space-size based on the server resources?

My application is constantly growing the memory usage and I'm trying to understand everything about node internals.

Hemeralopia answered 22/1, 2018 at 17:24 Comment(6)
I'm adding a comment now that I see I that this is getting view quiete a lot. It took me a full week to realise that my NodeJS app had no memory leak but that the garbage collector never kicked in. Be aware of this on systems with low memory like t2.micro or t2.small instances. Server is going to crash because of non-available RAM.Hemeralopia
Was there a way to get the garbage collector to kick in?Yama
@Hemeralopia why wasn't the garbage collector running?Fictitious
The configured max-old-space-size had a higher limit than the total amount of RAM that the machine had.Hemeralopia
Worth trying --optimize-for-size to reduce memory usage.Downgrade
@ZG101 To get the garbage collector to run, see #27322497Trashy
K
371

"Old space" is the biggest and most configurable section of V8's managed (aka garbage-collected) heap (i.e. where the JavaScript objects live), and the --max-old-space-size flag controls its maximum size. As memory consumption approaches the limit, V8 will spend more time on garbage collection in an effort to free unused memory.

If heap memory consumption (i.e. live objects that the GC cannot free) exceeds the limit, V8 will crash your process (for lack of alternative), so you don't want to set it too low. Of course, if you set it too high, then the additional heap usage that V8 will allow might cause your overall system to run out of memory (and either swap or kill random processes, for lack of alternative).

In summary, on a machine with 2GB of memory I would probably set --max-old-space-size to about 1.5GB to leave some memory for other uses and avoid swapping.

Krp answered 23/1, 2018 at 1:10 Comment(5)
That's exactly what I was hoping to get for an answer, describing the edge case where either the system or Node runs out of memory.Hemeralopia
@jmrk: Seems you are totally right, but when I am using 2GB RAM and 4GB swap and set "--max-old-space-size" to 4GB then node process consume all RAM memory and stuck on 1.9GB. The question is here "Why swap is avoid to use ?? " (Node version 8.11.1)Parmer
The flag should override anything else. Please double-check for typos.Krp
From d8 --help: --max-old-space-size (max size of the old space (in Mbytes))Krp
How can I solve it with 1GB RAM like "t2.micro"?Skimpy
T
197

2020 Update

These options are now documented officially by node. For a 2GB machine, you should probably use:

NODE_OPTIONS=--max-old-space-size=1536

What are 'new space' and 'old space' anyway?

There's an excellent answer on "what are new space and old space?".

To determine the amount to use

You can see available memory on a Linux machine using free -m. Note that you can consider the total of the free and the buffers/cache memory as available, as buffers/cache can be thrown away instantly when needed (these buffers and cache are a nice way to use otherwise unused memory).

The official documentation formax-old-space-size also mentions:

On a machine with 2GB of memory, consider setting this to 1536 (1.5GB)

Hence the value above. Consider that the amount of memory needed for the base OS doesn't change much, so you could happily do 3.5 on a 4GB machine etc.

To notice the defaults and see the effect of changes:

The default is 2GB:

$ node

> v8.getHeapStatistics()
{
  ....
  heap_size_limit: 2197815296,
}

2197815296 is 2GB in bytes.

When set to 8GB, you can see heap_size_limit changes:

$ NODE_OPTIONS=--max_old_space_size=8192 node
Welcome to Node.js v14.17.4.
Type ".help" for more information.
> v8.getHeapStatistics()
{
  ...
  heap_size_limit: 8640266240,
  ...
}

As @Venryx mentions below you can also use process.memoryUsage()

Trashy answered 19/8, 2020 at 21:33 Comment(11)
From the link you've shared from Node.js docs, it says: "On a machine with 2GB of memory, consider setting this to 1536 (1.5GB)"Davidson
Thanks @IdanDagan I'll add that to the answer.Trashy
Nitpick: there is no reason to prefer a "round number" here. 1535 or 1537 or 1500 or 1555 are just as good.Krp
That's true - but since memory is in bytes, we're just picking an even quarter portion of those bytes (performance concepts like NUMA/cache coherancy aside).Trashy
As an alternative to v8.getHeapStatistics(), you can also use: process.memoryUsage() (as seen here)Ulcer
Example says --max_old_space_size, but docs says --max-old-space-size. Bad copy paste?Hopson
@ShortFuse: both spellings work, you can use whichever you find easier to type.Krp
@Trashy You state the default is 2GB but I think the default is dynamic based on total system memory or something. For instance on a VM with ~21GB total ram, my heap_size_limit is 4345298944 or ~4GBCardon
Would nodejs with Worker Thread change that answer? for example, would we still want to keep 0.5GB less than available memory, or to leave 0.5GB * # Threads?Caudell
Hrm @LiranBrimer that's a good question - does each worker thread have it's own instance of v8?Trashy
My system's heap_size_limit is 4.3GB but Node 18 processes running on my machine that exceed that limit still succeed without throwing any error. Does anyone know why? They do throw the memory heap exceeded error when I run them on CI.Professorate
L
101

This error occurs when the memory allocated for the executing application is less than the required memory. By default, the memory limit in Node.js is 512 MB. To increase this amount, you need to set the memory limit argument —-max-old-space-size. It will help avoid a memory limit issue.

node --max-old-space-size=1024 index.js #increase to 1gb
node --max-old-space-size=2048 index.js #increase to 2gb
node --max-old-space-size=3072 index.js #increase to 3gb
node --max-old-space-size=4096 index.js #increase to 4gb
node --max-old-space-size=5120 index.js #increase to 5gb
node --max-old-space-size=6144 index.js #increase to 6gb
node --max-old-space-size=7168 index.js #increase to 7gb
node --max-old-space-size=8192 index.js #increase to 8gb

https://medium.com/@vuongtran/how-to-solve-process-out-of-memory-in-node-js-5f0de8f8464c

Lidless answered 30/6, 2020 at 4:26 Comment(12)
and it should be more than allocated Ram memoryHildredhildreth
I'm not sure this is true any more. Certainly on one system I have access to running node 10.20.1, I can see (with node --v8-options ) that the default reported is 4096 and without setting max-old-space-size the test suite i'm running gets up to 1.5Gb allocated with no trouble. The medium article linked is from 2016 so it is likely things have moved on since it was written.Marek
It's difficult to find corroboration on that; I can't find anything explicit in the docs for V8 or Node. Another system I have reports the default for v10, 12 & 14. as 0. FWIW I have found a couple of more recent bloggers stating max memory as 1.5Gb (tejom.github.io/general/nodejs/v8/debugging/2017/01/16/…) and that v12 has a dynamic max based on the system (idginsiderpro.com/article/3257673/…).Marek
node -e "console.log(`node heap limit = ${require('v8').getHeapStatistics().heap_size_limit / (1024 * 1024)} Mb`)" -> v12.18.0 and v14.3.0 -> 2096Mb, v10.20.1 -> 1432MbMarek
@JaySeeAre, thanks for that command to show the heap_size_limit. For a normal UNIX shell, it needs to be quoted differently: node -e 'console.log(`node heap limit = ${require("v8").getHeapStatistics().heap_size_limit / (1024 * 1024)} Mb`)'Rowney
Ahh nice. thanks. yeah i probably should have said i was on windows. :)Marek
I am using v12.16.3 --> 2096MBTweak
which index.js file to be referred here.? Is it a project js file.?Gully
I do not have index.js file in my project, somebody please help me out.Gully
@JaySeeAre What does the heap_size_limit mean here? The total available memory that node could used up to?Aciculum
@JaySeeAre Yes, this is the total amount of memory that Node can depend on while running a script.Roane
node -p '"heapSizeMb: " + require("v8").getHeapStatistics().heap_size_limit / (1024 * 1024) <- Try -p instead of -e and never worry about console.log again :) Also, wrap in new Object(...) for json outputKisor
M
8

To automagically determine correct --max-old-space-size and also leave some memory to kernel. here is a:

One Liner solution

NODE_OPTIONS=--max-old-space-size=$(expr $(echo "$(free -m)" | awk '/^Mem:/ {print $2}') - 512)

Output

Given conditions: total memory of my machine is 3907MB and leave 512 MB for kernel ie 3395MB for node. Tested on ubuntu 23. and node v20. works without giving you headache 👍.

echo $NODE_OPTIONS

--max-old-space-size=3395

Motheaten answered 2/11, 2023 at 21:37 Comment(0)
P
0

For me, Azure function invocations was terminating in a 7GB instance when the memory consumption is near to 2GB with the following error message.

Exception while executing function: Functions.graphql-mobile node exited with code 134
 [24164:000001CE2EB5CF00] 10557962 ms: Scavenge (reduce) 2041.0 (2050.5) -> 2040.1 (2051.5) MB, 2.3 / 0.1 ms  (average mu = 0.179, current mu = 0.002) allocation failure ,FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory, 3: 00007FF73E006026 node::OnFatalError+294 

I solved the issue by setting max-old-space-size like this in my application settings

"languageWorkers:node:arguments": "--max-old-space-size=5500"
Pastypat answered 15/9, 2021 at 14:12 Comment(0)
B
0

I think it depends on your running node.js app, some apps may require more memory than others. I had great success setting pm2 with the following option for node.js:

pm2 start <your-server.js> --watch --node-args="--max-old-space-size=512"

if your app crash too often (or instantly), then increase this to a higher value. There is no "right" value and probably this may need to be updated when your app is heavily used (you should monitor it and adjust accordingly).. probably a value of 1024 and + is a pretty safe to start with if you have loads of ram and are not on a budget VPS

Bioplasm answered 7/3 at 5:9 Comment(0)
P
0
"start": "node --max_old_space_size=8192 ./node_modules/@angular/cli/bin/ng serve --disable-host-check",

use this code to replace the start in your package.json file and start the angular application with npm run start, this is not a permanent solution but it will manage the application to work without the fatal error. (max_old_space_size=8192)-> will setout heap allocation for 8GB

Prothesis answered 14/3 at 9:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.