【问题标题】:Measuring time spent on GC在 JVM 中测量花费在 GC 上的时间
【发布时间】:2012-12-17 13:45:16
【问题描述】:

假设我正在测试一个 Java 服务器应用程序。我知道完成考试需要多少时间。现在我想知道在那次测试期间在 GC 上花了多少钱。我该怎么做?

【问题讨论】:

  • 我计算了在测试中端到端运行的时间,包括 GC 时间,并且我只在我想对其进行性能调整时将其分解,例如。使用内存分析器。

标签: java performance garbage-collection jvm qa


【解决方案1】:

我猜当 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;
}

【讨论】:

  • 这个答案太棒了。我在 GC 上执行了许多测试,GarbageCollectorMXBean 提供的值与 JVM args 写入的日志完全一样。
  • getGarbageCollectorMXBeans() 什么时候返回多个 mx bean?
【解决方案2】:

最简单的方法是在启动 JVM 时使用 -Xloggc-XX:-PrintGCTimeStamps 选项。我认为它会打印出垃圾收集需要多长时间。

http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html

【讨论】:

    【解决方案3】:

    此性能指标由 JVM 记录,并可通过 JMX 访问。对于交互式监控,使用 JConsole 连接到正在运行的 JVM,然后在“VM Summary”选项卡中会显示如下内容:

    垃圾收集器:名称 = '复制',集合 = 26,总花费时间 = 0.183 秒 垃圾收集器:名称 = 'MarkSweepCompact',集合 = 2,总花费时间 = 0.168 秒

    您还可以通过编程方式查询 JMX。

    【讨论】:

      【解决方案4】:

      另一个方便的解决方案是在测试完成后针对您的进程运行jstat -gc (documentation)。这将为您提供关于在 JVM 的生命周期中在 GC 中花费了多少时间的汇总输出。

      【讨论】:

        【解决方案5】:

        启用垃圾收集日志。作为documented,您可以使用-verbose:gc-XX:+PrintGCDetails-XX:+PrintGCTimeStamps 标志。 -Xloggc 标志可用于将它们定向到文件。

        生成的日志是人类可读的,但为了获得最大利益,您可能希望它们通过分析器运行。此类工具列于this thread

        【讨论】:

          【解决方案6】:

          有不同的 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 秒]

          【讨论】:

            【解决方案7】:

            类似于@Steve McLeod 使用ManagementFactory 的答案,因为Java 8 这也可以使用Java streams 在一行中编写:

            long collectionTime = ManagementFactory.getGarbageCollectorMXBeans().stream().mapToLong(mxBean -> mxBean.getCollectionTime()).sum();
            

            【讨论】:

            • getGarbageCollectorMXBeans() 什么时候返回多个 mx bean?
            • 我目前无法对其进行测试,但我很确定如果两个不同的收集器分别用于次要和主要收集,就会发生这种情况。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-11-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-03-26
            • 1970-01-01
            相关资源
            最近更新 更多