I'm running a dockerised node.js application on my server, using the --max-old-space-size
option to limit the applications heap size. The following output is given by htop:
PID USER PRI NI VIRT RES SHR S CPU% MEM% TIME+ Command
10158 root 20 0 4284 720 644 S 0.0 0.0 0:00.00 sh -c node --max-old-space-size=512 ./dist/www.js
10159 root 20 0 1841M 929M 29592 S 0.0 3.0 1h31:16 node --max-old-space-size=512 ./dist/www.js
10160 root 20 0 1841M 929M 29592 S 0.0 3.0 0:00.00 node --max-old-space-size=512 ./dist/www.js
10161 root 20 0 1841M 929M 29592 S 0.0 3.0 7:27.13 node --max-old-space-size=512 ./dist/www.js
10162 root 20 0 1841M 929M 29592 S 0.0 3.0 7:26.96 node --max-old-space-size=512 ./dist/www.js
10163 root 20 0 1841M 929M 29592 S 0.0 3.0 7:26.99 node --max-old-space-size=512 ./dist/www.js
10164 root 20 0 1841M 929M 29592 S 0.0 3.0 7:26.64 node --max-old-space-size=512 ./dist/www.js
You can see my applications resident memory (929M) is way above my max-old-space-size
value (512MB) so why is this being seen? Shouldn't the application have aborted by this point?
System Info
Docker version: 19.03.5
node image version: 11.13.0
uname -v
#31~18.04.1-Ubuntu SMP Tue Nov 17 10:48:34 UTC 2020
V8 developer here. The --max-old-space-size
flag does not directly control the overall process' memory consumption; it puts a limit on one part (the biggest part) of V8's managed (i.e. garbage-collected) heap, which is the chunk of memory where all the JavaScript objects are put. Aside from this "old space", V8 also has a (much smaller) "new space"; and besides V8's managed heap, there are a bunch of other consumers of memory in the process: for example, within V8, parser and compiler use memory outside the managed heap; and then aside from V8, Node puts a bunch of things in memory too. Depending on what exactly the embedder (i.e. Node) and the executing code do, large strings and ArrayBuffers can also live outside of the managed heap.
In short, --max-old-space-size
gives you one knob to affect how much memory will be used, but the limit you set there is not a limit for the process' overall memory consumption. (For comparison, in Chrome, typically about a third of a renderer process' memory is V8's managed heap, though depending on what websites do there are significant outliers in both directions. I don't know typical numbers for Node.)