Эффективный способ получить процессорное время потока, используя JMX - PullRequest
6 голосов
/ 09 июня 2009

В настоящее время я получаю общее время процессора потока с использованием JMX следующим образом:

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 (Runtime, Memory, GC), но они намного дешевле. Скорее всего, потому что каждый вызов thread.getThreadCpuTime является удаленным.

Обновление 2 : снимок экрана JProfiler, показывающий проблемы с производительностью.

alt text

Ответы [ 5 ]

3 голосов
/ 10 июня 2009

Если вы хотите использовать нестандартные API, вы можете привести OperatingSystemMXBean к com.sun.management.OperatingSystemMXBean и вызвать getProcessCpuTime(), как описано в Использование внутреннего класса Sun для получения времени ЦП JVM на Блог Дэвида Роберта Надо.

2 голосов
/ 19 сентября 2009

Проблема должна заключаться в удаленном характере ваших вызовов.

Недавно я сделал запрос на использование процессорного времени, и это было невероятно быстро. В контексте запроса веб-приложения это было почти неизмеримо. Если кто-то пойдет в жесткий цикл, это будет стоить вам, но обычно вы хотите это в начале операции и снова в конце.

1 голос
/ 26 марта 2013

Причиной плохой производительности является то, что каждый вызов thread.getThreadCpuTime() (в вашем случае удаленного прокси-сервера), скорее всего, приведет к вызову RMI / Remote JMX, что, конечно, дорого, особенно когда сообщение действительно отправляется через TCP (и, возможно, даже за пределами localhost). (см. Спецификацию JMX 1.4, глава 7.3)

Хотя JMX определяет одновременный поиск нескольких атрибутов , это вам здесь не поможет поскольку thread.getThreadCpuTime(long) является не атрибутом JMX, а удаленным вызовом метода (и, кроме того, объект ThreadInfo, для которого вызываются методы, отличается при каждом вызове)

К сожалению, спецификация JMX 1.4 не определяет что-то вроде "вызывать несколько методов нескольких объектов и вообще возвращать их возвращаемые значения" . Таким образом, помимо одновременного вызова (который сэкономит время, но не уменьшит усилия) этих вызовов, я не знаю о какой-либо (совместимой) оптимизации здесь.

1 голос
/ 10 июня 2009

Оптимизация:

  • вызовите getThreadCPUTime внутри пула потоков, поскольку он, похоже, связан с сетью;
  • всякий раз, когда обнаруживается, что поток находится в Thread.STATE.TERMINATED, сохраните его имя на карте и пропустите запрос в следующий раз.
0 голосов
/ 10 июня 2009

Не могли бы вы подробнее рассказать о том, как вы планируете использовать эту информацию? Вы можете получить процессорное время потоков, используя агент на основе JVMTI, который должен работать немного лучше, чем JMX. Как вы измерили издержки подхода JMX, которые привели вас к выводу о «ужасной» производительности?

...