Эффективный способ получить процессорное время потока, используя JMX

В настоящее время я получаю общее время процессора потока с использованием 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, показывающий проблемы с производительностью.

альтернативный текст

5 ответов

Решение

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

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

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

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

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

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

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

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

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

Другие вопросы по тегам