【发布时间】:2017-01-05 14:54:13
【问题描述】:
我最近正在测试一个并发负载相对较高的演示应用程序。该应用程序是一个 java 应用程序,在 Hotspot JVM (1.8.0_111) 上运行。
使用 4G 堆和并行吞吐量收集器,我可以获得大约 400 TPS 的最大吞吐量。吞吐量图表(作为负载的函数)如下所示。
因为 Oracle 建议对大于 4G 的堆大小使用 G1GC,所以我想尝试 G1,看看这是否对我的应用程序吞吐量有任何好处。
令我惊讶的是,使用 G1GC,我看到了以下吞吐量趋势。
我真的很惊讶,并决定深入了解这里发生了什么。这是我发现的。
我看到,最初,在 4G 堆中,1.5G 分配给老一代区域,2.5G 分配给伊甸区域。但是随着时间的推移,老一代不再适合 1.5G,堆的大小会被调整。这似乎无伤大雅。但问题似乎在于调整大小的方式。
现在所有 4G 都分配给老一代区域,几乎没有分配给伊甸园区域。现在,当需要将某些东西分配给伊甸园时,堆会再次调整大小。这已成为新常态,堆会反复调整大小,从而给应用程序带来巨大的性能成本。
有没有人在使用 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
【问题讨论】:
-
请问您可以分享您在应用程序启动期间设置的所有参数吗? docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/…
-
@SauliusNext 我现在已将参数列表添加到问题中。对于G1GC,唯一的区别是添加了-XX:+UseG1GC
-
由于您已经启用了 GC 日志记录,因此您应该附加一个足够长的感兴趣时间段的 GC 日志。
-
@SasidharSekar 我已代表您提交了一个问题bugs.openjdk.java.net/browse/JDK-8172354。请查看 Oracle 高级 GC 工程师“Thomas Schatzl”提供的建议,如果您需要进一步说明,请告诉我。
-
谢谢@Fairoz 这澄清了很多事情。我会尝试这些建议,看看情况如何改善。
标签: java jvm heap-memory hotspot g1gc