環境変数CLUSTER_WORKER_NODE_OPTIONSに--max-old-space-size=512を設定した後の経過観察
staging、jp.cosen.se、JKDセミオンプレにも設定した (2025/11/2 22:31)
予想shokai.icon
サービスの品質に影響はない
GCの開始が早まる
早まるだけで、起動から数時間後のGC頻度に差は生まれない
2025/11/4 14:52
https://scrapbox.io/files/692574c210003d6d446b7bf1.png
突き破ってるshokai.icon
メモリ使用量に対しては効果がない
突き出てる部分はちょうどmax swapの形に見える
https://scrapbox.io/files/692574c51cbf1f06aa2087e2.png
NodeのGCやEvent loopの負荷は下がっている
意図してない所に良い効果があったが
意図してた箇所が改善してない
もしかして、max-swapなども個別に何か設定しなければならないのか?shokai.icon
すみません調べて出直してきます
MAX SWAPは普通に我々の知っているswapの事で間違いないshokai.icon Swap: The portion of a dyno’s memory, in megabytes, stored on disk. It’s normal for an app to use a few megabytes of swap per dyno. Higher levels of swap usage though may indicate too much memory usage when compared to the dyno size. This can lead to slow response times and should be avoided. Max swap is reported for each 10 or 1 minute interval.
単純にdyno増やすしかないのかなshokai.icon
たぶんこういう事shokai.icon
OSは、メモリの圧が高まるとswapに逃がす
nodeはもっと確保できると思って、確保してしまう
正確にはメモリ確保をトライしてしまい、そして通る
そうっぽいshokai.icon
何が起きているかを解説しますChatGPT.icon
1. Node がメモリを要求する
2. Linux カーネルは “今は空きを作れるか” を判断して応じる(=割り当ては一旦通る)
Linux は「ページ再回収(page reclaim)」で空きページを作ります。空きが減るとkswapdなどが起きて Inactive リストからページを回収します。匿名ページは スワップへ書き出して空きを捻出します。これにより、新たな割り当てが成功し続けることがあります。 (wiki.bit-hive.com) 3. (必要なら)スワップを使ってさらに延命
カーネルはファイルキャッシュを捨てたり匿名ページをスワップに出したりして空きを確保し、物理 RAM 不足でもプロセスを即クラッシュさせず動かし続けます(swappiness で挙動を調整可能)。活発に使われていないページから優先して追い出すのが基本です。 (docs.kernel.org) 4. だから “割り当ては通る” が、裏ではスワップ使用量が増える
結果として、Node の要求は成功 → OS は裏でページを追い出す/スワップする → 体感はしばらく動くが、スワップ占有がじわじわ増加し、I/O 待ちで遅くなる、という流れになりがちです。RHEL8 の解説でも「非アクティブ匿名ページをスワップして page cache を保つ」等のバランス変更が述べられています(=使ってない匿名ページは積極的に外へ)。 (Red Hat Customer Portal) 5. オーバーコミットの存在で“予約だけは通る”ことも
Linux は既定で メモリのオーバーコミット(合計RAM+スワップ等を見て大きすぎる要求以外は通す)を許容します。実使用が膨らんで実際に足りなくなると、回収やスワップ、それでもダメなら OOM Killer へ、という段階的挙動です。 (docs.redhat.com) 6. Node 視点での観測ポイント
process.memoryUsage() の rss(プロセス全体)と heapUsed(JS ヒープ)・external/arrayBuffers(オフヒープ)を見比べると、ヒープ外が太っていないかが分かります。Node 公式の診断ドキュメントや API で説明されています。Buffer/ArrayBuffer は V8 ヒープ外のメモリを持ちうる点も歴史的な doc に明記。 (nodejs.org) もう少し丁寧に:各段の裏付け
ページ再回収とスワップ
カーネルは空きが減ると kswapd/直接回収で LRU をスキャンし、匿名ページはスワップへページアウトして空きを作る(shrink_list の処理)。 (wiki.bit-hive.com) Linux の VM チューニング項目 /proc/sys/vm/* は公式 docs にまとまっており、vm.swappiness は「どれだけ積極的にスワップするか」を決めます。 (docs.kernel.org) Swappiness と実挙動
Arch Wiki でもスワップの基礎・swappiness の意味が整理されています(デフォルト 60、値が小さいほど匿名ページをなるべく残し file cache を先に解放)。RHEL の資料は cgroup と swappiness の関係やデフォルトの意味合いも詳しい。 (wiki.archlinux.jp) オーバーコミット
既定(vm.overcommit_memory=0)では「概ね通す」ポリシー。必要時は回収/スワップ、限界で OOM。設計とパラメータは kernel docs/Red Hat docs に明記。 (kernel.org) Node/V8 の上限と観測
Node 公式 “Understanding and Tuning Memory” で V8 ヒープと --max-old-space-size の話、process.memoryUsage() は API docs から。Buffer が V8 ヒープ外である点は古いが明確な Node 公式ドキュメント文言が残っています(挙動の本質は現在も同様:巨大 Buffer は RSS を押し上げる)。 (nodejs.org) 結論
あなたの理解(「OS が仮想メモリで延命 → Node の確保が通る → スワップが増える」)は、Linux VM の設計と Node/V8 の動作に照らして正しいです。
実務では、rss と heapUsed/external の差分監視 + swap in/out(vmstat 1 の si/so)で「延命の代償としてスワップが増えていないか」を見るのがおすすめです。
合計900MBぐらいにしておく
もっと小さくした方が良いChatGPT.icon
--max-old-space-size の合計を 1GB 未満に抑えるだけでは不十分。
各プロセスの オフヒープ(Buffer/TypedArray のバックストア等)+コード領域+スタック+mmap が乗ります。
bufferとかって別領域なんだshokai.icon
目安として、ヒープ上限=想定RSSの 50–70% 程度から始めると安全です。
OS/コンテナ側でも上限を“物理的”に掛ける(cgroup/K8s/Docker)と、スワップ頼みの延命を抑えられます。
その領域をHerokuでは触れないので、アプリ側が自主規制するしかないんだよなーshokai.icon
こうするChatGPT.icon
OS/ファイルキャッシュ用に 150–200MBは最低確保
残り ~800–850MB を Node 群に割り当て
scrapbox.ioに設定した (2025/11/4 19:27)
jp.cosen.seには--max-old-space-size=450を設定した (2025/11/4 21:17)
2.5GBメモリをworker 5プロセス + master 1プロセスなので、worker1つあたり450MBぐらいでいいだろうという計算
2025/11/5 17:50
https://scrapbox.io/files/692574bf6b270176228478a7.png
気持ちゆるやかになったような気もするけど、ほぼ効果なしshokai.icon