Ruby memory bloat
If your app is suffering from high memory usage, it’s best to investigate memory bloat first given it’s an easier problem to solve than a leak.
Rubyはオブジェクトを管理するためにRuby heap pageを持つ 40 bytesのスロットに分割され、1スロットに1オブジェクトを格納する
足りない場合はポインタを持つ
空きスロットがないときはヒープページを割り当てる
呼び出し元が要求するよりも多くのメモリを確保してしまうので余る。この余りがなくなるまで割り当て続ける
カーネル
4KB単位でしか割り当てられない。この単位をページという(OSページ) パフォーマンス影響が大きいので極力呼び出しを減らしたい
topやpsでメモリ使用量を確認すると、カーネル観点でのメモリ使用量が表示される 実際には使われていない領域も含まれる
断片化
Rubyレベル
RubyのGCではRuybヒープページのスロットを空きとしてマークし、再利用できるようにする ヒープページすべてが空きスロットになったらmemory allocatorを介して解放することができる
スロットが少しでも空いていない場合は解放できず、カーネルから見れば使用中
OSページに対しても同じことが起きうる
すべてが空いていなければ解放できず、1ページの空き領域で不足する場合は新たなページ割り当てを要求する
複数のスレッドで同じOSヒープを扱うと競合するので、memory allocatorは複数のOSヒープを作成して各スレッドに割り当てる
memory allocatorはRedHatが商用サーバ向けを想定して開発している OSページを解放するC関数
jemallocにより改善するケースも知られているが、versionによる差異もあるのでRubyのデフォルトにできるほど安定していない