以下の環境とテストでCMSとG1GCを比較してみた。かなり急ぎでやったので間違っている可能性が多少ある。
- 16 cores, 32GB mem
- -Xms24g -Xmx24g
- 8 instances Infinispan 6.0.3.Final DIST cache, put 4GB data (1KB entry * 2M, 2GB data with one backup copy, 2GB * 2 = 4GB)
- CMS: -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=30
- G1GC: -XX:+UseG1GC -XX:G1HeapRegionSize=16m -XX:InitiatingHeapOccupancyPercent=30
$ java -XX:+UseG1GC -XX:+PrintFlagsFinal -version | grep -E 'MaxGCPauseMillis|G1HeapRegionSize|InitiatingHeapOccupancyPercent|ParallelGCThreads|ConcGCThreads' uintx ConcGCThreads := 3 {product} uintx G1HeapRegionSize = 0 {product} uintx InitiatingHeapOccupancyPercent = 45 {product} uintx MaxGCPauseMillis = 200 {product} uintx ParallelGCThreads = 13 {product}
CMSでGCが間に合わなくてFull GCが発生してしまっている、もしくはFull GCにこそなっていないもののヒープ最大近くまで消費しているケースでG1GCにスイッチするともっとFull GCが起こる。G1GCはそもそも高スループットGCという位置付けではない。
重要なのはポーズタイムだ。CMSでポーズタイムが問題になっている、ヒープはいくらでも増やせるがCMSでこれ以上ヒープ増やすとポーズタイムも一緒に増えて困るよね、というときにG1GCの出番だ。