Недавно я тестировал приложение для презентаций с относительно высокой одновременной нагрузкой. Приложение представляет собой Java-приложение и работает на Hotspot JVM (1.8.0_111).
Я мог получить максимальную пропускную способность около 400 TPS с кучей 4G и параллельным сборщиком пропускной способности. График пропускной способности (в зависимости от нагрузки) показан ниже.
Поскольку Oracle предлагает использовать G1GC для размеров кучи больше 4G, я хотел попробовать G1 и посмотреть, улучшит ли это каким-либо образом пропускную способность моего приложения.
К моему удивлению, с G1GC я увидел тенденцию пропускной способности ниже.
Я был искренне удивлен и решил покопаться в нем, чтобы посмотреть, что здесь произошло. Вот что я нашел.
Я вижу, что изначально из кучи 4G выделено 1,5G для регионов old 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 можно найти здесь