トップ 差分 一覧 ソース 置換 検索 ヘルプ PDF RSS ログイン

Sidekiqのメモリ使用量増え続ける

参考

https://techracho.bpsinc.jp/hachi8833/2017_12_28/50109
https://qiita.com/kamina_zzz/items/0540f663832e07ee1b10
http://www.rarul.com/mt/log/2018_09.html
https://qiita.com/kaityo256/items/bf6563361c502bbf062e

概要

RubyのSidekiqなどのマルチスレッド処理でメモリの使用量が増え続けてしまうことがある。
メモリリークしているわけではなく、Rubyのメモリ管理とmallocの仕様によりメモリの断片化が発生している。

メモリリークのようにメモリを消費し続けるわけではなく、対数的にある上限に収束するように増加する。

mallocはマルチスレッドでの排他処理の効率を上げるためにスレッド単位メモリアリーナを実装している。
以下引用

1. あるスレッドでmallocを呼び出します。このスレッドは、前回アクセスしたメモリアリーナ(他のアリーナが作成されていない場合はメインのアリーナ)のロック取得を試みます。
2. そのアリーナを利用できない場合は、次のメモリアリーナのロック取得を試みます(メモリアリーナが他にもある場合)
3. 利用できるアリーナがない場合は、アリーナを1つ作成してそれを使う。この新しいアリーナは、連結リストの最後のアリーナにリンクされる。

マルチスレッドかつI/O処理を実行するCRubyにスレッド単位メモリアリーナが使われ、新しいメモリアリーナが大量に作成されてしまう。
マルチスレッドでもI/Oを行っていない場合はGVM(Global VM Lock)によって制御されるためメモリアリーナの奪い合いは発生しない。

解決策

 方法1:メモリアリーナを削減する

MALLOC_ARENA_MAX環境変数でメモリアリーナの最大数を設定できる。
メモリアリーナ数を調整することでメモリの使用量を減らすことが出来るが、排他処理が多くなるためパフォーマンスの低下に繋がる。
メモリの使用量とパフォーマンスのバランスを確認しながら設定する必要がある。

 方法2:jemallocを使う

アロケータをmallocからjemallocに変更する。
jemallocもスレッド単位アリーナを実装していますが、mallocで起きる断片化を回避する設計になっている。

[カテゴリ: プログラミング言語 > Ruby]



  • Hatenaブックマークに追加
  • livedoorクリップに追加
  • del.icio.usに追加
  • FC2ブックマークに追加

最終更新時間:2019年04月07日 13時29分20秒