😀

Node.jsの--max-old-space-sizeのデフォルト値はメモリサイズによって変わりそう

2025/03/09に公開

背景

64bit環境ではNode.jsの--max-old-space-sizeのデフォルト値が1400MiBに制限されていると記載されている記事がいくつか見つかりましたが、ローカルのM1 MacのNode.jsのプロセスが--max-old-space-sizeを指定していないのに、明らかに1400MiB以上使っているため、疑問に思って調べてみました。

環境

Mac M1 32GB

調査

オプションを指定せずにNode.jsを起動し、V8のヒープサイズ制限を確認してみます。

❯ node -e 'console.log(Math.floor(v8.getHeapStatistics().heap_size_limit/1024/1024))'
4144

4144MBが設定されています。

ヒープメモリ関連のコードを追うと以下のロジックが見つかりました(全体のソースコードは把握できていないです)
64ビットシステムかつメモリが15GB以上であればヒープサイズを2GBから4GBに増やしているようです。このロジックの挙動になっていれば4144MBが設定されているのも辻褄が合いそうです。
https://github.com/nodejs/node/blob/309924f65d3cfa562a49fca8667f58fdea2759a6/deps/v8/src/heap/heap.cc#L369-L382

検証

上記のロジックの挙動になっているか簡単に確認してみます。
multipassで16GB,8GBの仮想マシンを起動してNode.jsを実行してみます。

multipass launch --memory 8GB --name test1
multipass launch --memory 16G --name test2

8GBメモリ

node -v
v22.14.0
cat /proc/meminfo | grep MemTotal
MemTotal:        8110704 kB
node -e 'console.log(Math.floor(require("v8").getHeapStatistics().heap_size_limit / 1024 / 1024) + " MB")'
2096 MB

デフォルト値は2096MBが設定されています。

16GBメモリ

node -v
v22.14.0
cat /proc/meminfo | grep MemTotal
MemTotal:       16339536 kB
node -e 'console.log(Math.floor(require("v8").getHeapStatistics().heap_size_limit / 1024 / 1024) + " MB")'
4144 MB

デフォルト値は4144MBが設定されています。

最後に

今回の検証で物理メモリによって--max-old-space-sizeが動的に割り当てられることが分かりました。以前、GitHub Actions上でheap out of memoryのエラーが発生し、ローカルでは問題ないのになぜ?(どちらも1400MiBに割り当てられているならローカルも落ちるはずでは?)と思うことがありましたGithub Actionsの方がメモリが少なく、--max-old-space-sizeが少なめに割り当てられていたから落ちていたのかなと納得できました。
この調査では一部のソースコードしか確認できていないため、もし誤りがあればご指摘いただけるとありがたいです。

参考記事

https://zenn.dev/legalscape/articles/a0715a699eacb5
https://qiita.com/kawanet/items/cfedd535990b32710c50

Discussion