【发布时间】:2012-12-17 13:45:16
【问题描述】:
假设我正在测试一个 Java 服务器应用程序。我知道完成考试需要多少时间。现在我想知道在那次测试期间在 GC 上花了多少钱。我该怎么做?
【问题讨论】:
-
我计算了在测试中端到端运行的时间,包括 GC 时间,并且我只在我想对其进行性能调整时将其分解,例如。使用内存分析器。
标签: java performance garbage-collection jvm qa
假设我正在测试一个 Java 服务器应用程序。我知道完成考试需要多少时间。现在我想知道在那次测试期间在 GC 上花了多少钱。我该怎么做?
【问题讨论】:
标签: java performance garbage-collection jvm qa
我猜当 GC(垃圾收集器)工作时,应用程序会停止并在 GC 完成后恢复
我不认为这是一个安全的假设。您确定垃圾收集器没有与您的应用程序代码并行工作吗?
要测量收集垃圾所花费的时间,您可以查询Garbage Collector MXBean。
试试这个:
public static void main(String[] args) {
System.out.println("collectionTime = " + getGarbageCollectionTime());
}
private static long getGarbageCollectionTime() {
long collectionTime = 0;
for (GarbageCollectorMXBean garbageCollectorMXBean : ManagementFactory.getGarbageCollectorMXBeans()) {
collectionTime += garbageCollectorMXBean.getCollectionTime();
}
return collectionTime;
}
【讨论】:
GarbageCollectorMXBean 提供的值与 JVM args 写入的日志完全一样。
getGarbageCollectorMXBeans() 什么时候返回多个 mx bean?
最简单的方法是在启动 JVM 时使用 -Xloggc 和 -XX:-PrintGCTimeStamps 选项。我认为它会打印出垃圾收集需要多长时间。
http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html
【讨论】:
此性能指标由 JVM 记录,并可通过 JMX 访问。对于交互式监控,使用 JConsole 连接到正在运行的 JVM,然后在“VM Summary”选项卡中会显示如下内容:
垃圾收集器:名称 = '复制',集合 = 26,总花费时间 = 0.183 秒 垃圾收集器:名称 = 'MarkSweepCompact',集合 = 2,总花费时间 = 0.168 秒
您还可以通过编程方式查询 JMX。
【讨论】:
另一个方便的解决方案是在测试完成后针对您的进程运行jstat -gc (documentation)。这将为您提供关于在 JVM 的生命周期中在 GC 中花费了多少时间的汇总输出。
【讨论】:
启用垃圾收集日志。作为documented,您可以使用-verbose:gc、-XX:+PrintGCDetails 和-XX:+PrintGCTimeStamps 标志。 -Xloggc 标志可用于将它们定向到文件。
生成的日志是人类可读的,但为了获得最大利益,您可能希望它们通过分析器运行。此类工具列于this thread。
【讨论】:
有不同的 GC 算法表现不同。我最近阅读了一篇关于该主题的good article,如果您想了解更多信息,我可以推荐它。
您可以使用以下命令行选项-verbose:gc -XX:+PrintGCDateStamps -XX:+PrintGCDetails 启动您的应用程序并获取有关 GC 的信息。
以下是日志消息的示例:
2012-12-17T03:02:15.590-0500: [GC [PSYoungGen: 40934K->2670K(29440K)] 48211K->14511K(73152K), 0.5745260 secs] [Times: user=0.08 sys=0.01, 真实=0.58 秒]
【讨论】:
类似于@Steve McLeod 使用ManagementFactory 的答案,因为Java 8 这也可以使用Java streams 在一行中编写:
long collectionTime = ManagementFactory.getGarbageCollectorMXBeans().stream().mapToLong(mxBean -> mxBean.getCollectionTime()).sum();
【讨论】:
getGarbageCollectorMXBeans() 什么时候返回多个 mx bean?