2021-11-11 Ruby: mallocでマルチスレッドプログラムのメモリが倍増する理由 / jemallocs vs tcmallocs vs mimalloc
Ruby: mallocでマルチスレッドプログラムのメモリが倍増する理由(翻訳)|TechRacho by BPS株式会社
解決策としては以下2つ。
- メモリアリーナを削減する
MALLOC_ARENA_MAX
を 2-4 に設定する
- jemallocを使う
- malloc → jemalloc に変更
LD_PRELOAD
で動的に読み込み可能
- GC compaction
- ref. GC.compact (Ruby 3.0.0 リファレンスマニュアル)
- sidekiq(enterprise) とか puma とかにはコード内に入っている
本番でRubyとPumaまたはSidekiqを使うときは常にjemallocを使うことをおすすめしたいと思います。
プロダクションの Rails サーバーの利用メモリがひたすら増加していくような挙動を観測したとき、どう対応するのがよいですか? - Quora
太古の昔から現在に至るまで、Railsのメモリ使用量がじわじわ増え続ける問題は解決できていません。というのも、これは使われないメモリへの参照が残るバグとしてのmemory leakではなくて、ちゃんと開放してるにもかかわらずメモリ使用量が減らないmemory bloatだからです。
なぜmemory bloatが起きるのか?ですが、これは主にメモリのフラグメンテーション(断片化)の問題です。メモリを確保したり開放したりを繰り返すうちに、再利用しにくい小さい隙間がだんだん増えていくという現象です。
この断片化はRubyレベルだけでなく、さらに下のメモリアロケータレベルでも発生するので、実態はかなり複雑です。 後者については、Glibc malloc特有の挙動があって、PumaやSidekiqなどのスレッドをヘビーに使う環境ではjemallocに置き換えただけでかなり改善するという報告も多数あります。
jemallocs vs tcmallocs vs mimalloc
jemalloc 以外にも allocator がいろいろある。
それぞれ Meta(Facebook), Google, MS などのビッグテックが関わっている。