使用JMX获取线程CPU时间的有效方法

我目前使用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屏幕截图。

替代文字

如果您愿意使用非标准API,则可以将OperatingSystemMXBeancom.sun.management.OperatingSystemMXBean并调用getProcessCpuTime() ,如使用Sun内部类在David Robert Nadeau的博客上获取JVM CPU时间中所述 。

必须是您的呼叫的远程性质才是问题所在。

我最近在询问一个线程的CPU时间使用时出现了高峰,而且速度非常快。 在Web应用程序请求的上下文中,它几乎是无法估量的。 如果一个人进入硬循环,它会花费你,但通常你想在操作开始时和最后一次。

最佳化:

  • 在线程池中调用getThreadCPUTime,因为它似乎是网络绑定的;
  • 每当发现一个线程在Thread.STATE.TERMINATED ,将其名称保存在Map中并在下次跳过查询。

性能不佳的原因是每次调用thread.getThreadCpuTime()都会(在远程代理的情况下)最有可能导致RMI / Remote JMX调用,这当然是昂贵的,特别是当消息实际通过TCP(甚至可能在localhost之外)。 (参见JMX 1.4规范,第7.3章)

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

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

您能详细谈谈您计划如何使用这些信息吗? 您可以使用基于JVMTI的代理获取线程CPU时间,该代理的性能应该略好于JMX。 您是如何衡量JMX方法的开销导致您获得“可怕”性能的结论?