6

我目前正在通过以下方式使用 JMX 获取总线程 CPU 时间:

private long calculateTotalThreadCpuTime(ThreadMXBean thread) {

    long totalTime = 0l;

    for (ThreadInfo threadInfo : thread.dumpAllThreads(false, false))
        totalTime += thread.getThreadCpuTime(threadInfo.getThreadId());

    return totalTime;
}

由于 ThreadMXBean 实际上是一个远程代理,因此性能非常糟糕,对于这个实际的方法调用来说只有几秒的数量级。

有没有更快的方法来做到这一点?


更新:我用它来监控性能。测量结果是“挂钟”时间和 JProfiler,这表明我大约 85% 的时间都花在了这种方法上。我确实有其他一些 MXBean 调用(运行时、内存、GC),但它们要便宜得多。很可能是因为每次调用thread.getThreadCpuTime都是远程调用。

更新 2:显示性能问题的 JProfiler 屏幕截图。

替代文字

4

5 回答 5

3

如果您愿意使用非标准 API,您可以强制OperatingSystemMXBean转换为com.sun.management.OperatingSystemMXBean和调用getProcessCpuTime(),如David Robert Nadeau 的博客上的使用 Sun 内部类获取 JVM CPU 时间中所述。

于 2009-06-09T22:56:59.640 回答
2

问题一定是您的呼叫的远程性质。

我最近在向线程询问 CPU 时间使用时做了一个高峰,它的速度快得令人难以置信。在 Web 应用程序请求的上下文中,它几乎是不可估量的。如果一个人进入一个硬循环,它会花费你,但通常你希望它在操作开始时并在结束时再次出现。

于 2009-09-19T07:53:46.180 回答
1

性能不佳的原因是每次调用thread.getThreadCpuTime()will(在您的远程代理的情况下)最有可能导致 RMI/远程 JMX 调用,这当然是昂贵的,尤其是当消息实际上是通过 TCP 发送时(甚至可能本地主机之外)。 (参见 JMX 1.4 规范,第 7.3 章)

尽管 JMX 一次定义了多个属性检索,但这在这里对您没有帮助,因为thread.getThreadCpuTime(long)它不是 JMX 属性而是远程方法调用(此外,调用方法的 ThreadInfo 对象因每次调用而异)

不幸的是,JMX 1.4 规范没有定义诸如“调用多个对象的多个方法并完全返回它们的返回值”之类的东西。因此,除了这些调用的并发调用(这将节省时间但不会减少工作量)之外,我不知道这里有任何(兼容的)优化。

于 2013-03-26T18:48:25.507 回答
1

优化:

  • 在线程池中调用 getThreadCPUTime,因为它似乎是网络绑定的;
  • 每当发现线程在 中时Thread.STATE.TERMINATED,将其名称保留在 Map 中,下次跳过查询。
于 2009-06-10T09:07:53.397 回答
0

你能多谈谈你打算如何使用这些信息吗?您可以使用基于 JVMTI 的代理获取线程 CPU 时间,该代理的性能应该比 JMX 稍好。您如何衡量导致您得出“糟糕”性能结论的 JMX 方法的开销?

于 2009-06-09T20:05:14.963 回答