最近、同時負荷が比較的高いプレゼンテーション アプリをテストしていました。アプリケーションは Java アプリケーションであり、Hotspot JVM (1.8.0_111) で実行されています。
4G ヒープと並列スループット コレクターを使用して、約 400 TPS の最大スループットを得ることができました。スループット グラフ (負荷の関数として) を以下に示します。
Oracle は 4G を超えるヒープ サイズには G1GC を使用することを推奨しているため、G1 を試して、これがアプリケーションのスループットに何らかのメリットがあるかどうかを確認したいと思いました。
驚いたことに、G1GC では、以下のスループット傾向が見られました。
私は本当に驚き、ここで何が起こったのかを調べることにしました。これが私が見つけたものです。
最初に、4G ヒープのうち、1.5G が古い gen リージョンに割り当てられ、2.5G が eden リージョンに割り当てられていることがわかります。しかし、時間が経過し、古い世代が 1.5G に収まらなくなると、ヒープのサイズが変更されます。これは無害に思えます。しかし、問題はサイズ変更の方法にあるようです。
現在、すべての 4G が古い世代のリージョンに割り当てられており、eden リージョンにはほとんど割り当てられていません。現在、何かを Eden に割り当てる必要がある場合、ヒープのサイズが再度変更されます。そして、これが新しい標準となり、ヒープのサイズが繰り返し変更され、アプリケーションのパフォーマンスに多大なコストがかかります。
G1GCでこれに気付いた人はいますか? この問題を交渉するための推奨事項はありますか?
以下は、JVM オプションを指定した起動コマンド ラインです。
java -server -Xms4096m -Xmx4096m -XX:MetaspaceSize=100m -XX:MaxMetaspaceSize=100m -XX:MaxDirectMemorySize=512m -XX:MinMetaspaceFreeRatio=0 -XX:MaxMetaspaceFreeRatio=100 -XX:CompressedClassSpaceSize=20m -XX:InitialCodeCacheSize=50m -XX:ReservedCodeCacheSize=50m -XX:+AlwaysPreTouch -XX:+DisableExplicitGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/tmp -Xloggc:/servers/logs/gc.log.2017-01-05-085234 -Djava.awt.headless=true -XX:+UnlockCommercialFeatures -XX:+FlightRecorder -Dio.netty.leakDetectionLevel=simple -XX:MaxDirectMemorySize=512m -Dadmin.connectors.http.port=9000 -Dproxy.connectors.http.port=8080 -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=8654 -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -server -cp ...
JVM オプション:
-server
-Xms4096m
-Xmx4096m
-XX:MetaspaceSize=100m
-XX:MaxMetaspaceSize=100m
-XX:MaxDirectMemorySize=512m
-XX:MinMetaspaceFreeRatio=0
-XX:MaxMetaspaceFreeRatio=100
-XX:CompressedClassSpaceSize=20m
-XX:InitialCodeCacheSize=50m
-XX:ReservedCodeCacheSize=50m
-XX:+AlwaysPreTouch
-XX:+DisableExplicitGC
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/var/tmp
-Xloggc:/servers/logs/gc.log.2017-01-05-085234
-Djava.awt.headless=true
-XX:+UnlockCommercialFeatures
-XX:+FlightRecorder
-Dio.netty.leakDetectionLevel=simple
-XX:MaxDirectMemorySize=512m
-Dadmin.connectors.http.port=9000
-Dproxy.connectors.http.port=8080
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=8654
-Dcom.sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-server
-cp ...
ここで gc ログを見つけてください