【Java】CMS
CMS
CMS(Concurrent Mark & Sweep)コレクタは、Javaで用いられるガーベジコレクタです。従来の世代別GC方式を採用していますが、Old領域のGC処理をコンカレントGCと呼ばれる手法によって行います。
従来の世代別GC
従来の世代別GCでは、ヒープをNew領域とOld領域に分け、New領域をさらにEden領域、Seveive(From/To)領域に分割します。新しく生成したオブジェクトはEden領域に格納され、New領域に対しては頻繁にMark&CopyによるGCが適用されます(コピー先はServive領域)。Servive領域内である一定回数GCの対象とならなかったオブジェクトはOld領域に移動し、以降はMixedGC、FullGCでのみGC対象となります。
Old領域に対するGCにはMark&Sweepが用いられます。Mark&Sweepは非GC時のパフォーマンスが良いので不要になりにくいオブジェクトが集まるOld領域にはうってつけなのですが、GC時のパフォーマンスはMark&CopyGCを下回ります。そのため、Old領域のGC=実行時間コストが大きいのです。
仮にネットワーク処理やIOであれば別スレッドの並列実行が可能ですが、GCはそもそもアプリケーションが使うメモリ上のオブジェクトデータを操作してしまうので、並列実行による裏方処理ができません。
そこで、Old領域のGC時間を最小にするコンカレントGCが登場しました。
コンカレントGC
コンカレントGCではGC処理を以下の4つフェーズに分割し、アプリケーションの停止時間が少なくなるように各フェーズを実行します。アプリケーションスレッドの動作に影響がない処理であれば、別スレッドで並列実行します。
- Initial Mark
- Concurrent Mark
- Remark
- Concurrent Sweep
Initial Mark
Mark & Sweep同様、被参照オブジェクトに印をつけるフェーズです。この処理は、全てのアプリケーションスレッドが停止する必要のある動作です。
Concurrent Mark
アプリケーションスレッドの処理と並列させながら動作するマーク作業。アプリケーションを動かしつつマークするので、例えばマークされているオブジェクトが参照されなくなっている、マークが付いていないオブジェクトだが参照されている等の矛盾が発生してしまいます。
Renark
Concurrent Markフェーズのマークの整合性をチェックします。この作業はアプリケーションと同期する必要があります。
Concurrent Sweep
マークの付いていないオブジェクトをSweepします。既に使われていないオブジェクトの破棄作業なので、アプリケーションスレッドと並列に動作できます。
Mark&Sweepの動作を4フェーズに分けたことで、内2フェーズを並列処理で実行することができています。
CMSの推奨環境
- マシンが複数プロセッサを搭載している
- ヒープに格納されるオブジェクト量が多く、比較的短命である
- アプリケーション内でGCによる一時停止時間を短くしたい
参考文献
“Stop the World”を防ぐコンカレントGCとは?:現場から学ぶWebアプリ開発のトラブルハック(2) - @IT