我最近测试了一个并发负载相对较高的演示应用程序,该应用程序是一个java应用程序,运行在Hotspot JVM(1.8.0_111)上。
使用4G堆和并行吞吐量收集器,我可以获得大约400 TPS的最大吞吐量。
因为Oracle建议对大于4G的堆使用G1GC,所以我想尝试G1,看看这是否对我的应用程序吞吐量有任何好处。
令我惊讶的是,在G1GC中,我看到了吞吐量趋势。
我真的很惊讶,决定深入研究一下,看看这里发生了什么。
我看到最初,在4G的堆中,1.5G被分配给了old gen区域,2.5G被分配给了eden区域。但是随着时间的推移,old gen不再适合1.5G,堆被调整了大小。这看起来是无害的。但是问题似乎在于调整大小的方式。
现在所有的4G都被分配给了旧的gen区域,几乎没有一个被分配给eden区域。现在,当有东西需要被分配给eden时,heap会再次调整大小。这成为了新的常态,heap会反复调整大小,从而导致应用程序的巨大性能开销。
有没有人注意到这一点之前与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日志here
1条答案
按热度按时间unftdfkk1#
以下两种GC原因似乎有很多:
巨大的分配需要老一代的空间,对空间的消耗推动了年轻一代的规模。他们基本上是在相互竞争。
看起来你分配了很多巨大的对象(〉1/2 G1区域大小),速度比IHOP启动的并发周期收集它们的速度还快。
你可以试着增加区域的大小。如果它们是大的原始数组(即不是引用arrasy),那么实验性的eager reclaim feature也会有帮助。