Измерение времени выполнения Java, использования памяти и загрузки процессора для сегмента кода

Для определенного сегмента кода Java я бы хотел измерить:

  • Время выполнения (наиболее вероятное время выполнения потока)
  • Использование памяти
  • Нагрузка на процессор (конкретно относится к сегменту кода)

Я относительный новичок в Java и не знаю, как этого достичь. Меня упоминали в JMX, однако я не уверен, как это можно использовать, и JMX выглядит немного "тяжело" для того, что я собираюсь сделать.

В идеале я хотел бы, чтобы какой-то класс измерения мог бы сказать, что я хотел бы измерить, с возможностью вызова start() метод до сегмента кода и stop() метод после. Соответствующие метрики будут записываться в указанный мной файл.

Например:

import com.example.metricLogger;

metricLogger logger = new metricLogger();

logger.setLogPath(pathToLogFile);
logger.monitor(executionTime);
logger.monitor(memoryUsage);
logger.monitor(cpuLoad);

logger.start();

/* Code to be measured */

logger.stop();

Есть ли какой-нибудь стандартный / общий / традиционный способ достижения этого в Java?

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

Я более чем рад, что меня отсылают к учебным пособиям или внешним примерам, и я не ожидаю полного ответа здесь. Тем не менее, если что-то столь простое, как вышеперечисленное, может быть достигнуто, реалистичный пример получился бы действительно удачным.

3 ответа

Решение

Профилирование может быть проще, так как вам не нужна статистика производства. Профилирование также не требует модификации кода. VisualVM (который поставляется с JDK 1.6.06+) - это простой инструмент. Если вы хотите что-то более глубокое, я бы выбрал Eclipse TPTP, Netbeans Profiler или JProfiler(платно).

Если вы хотите написать свой собственный, подумайте о следующем:

Простые измерения, такие как время выполнения, можно выполнить путем "синхронизации" интересующего вас раздела:

long start = System.nanoTime(); // requires java 1.5
// Segment to monitor
double elapsedTimeInSec = (System.nanoTime() - start) * 1.0e-9;

Вы можете использовать похожую технику для мониторинга памяти с помощью методов Runtime.getRuntime().* Memory(). Имейте в виду, что отслеживание использования памяти в среде сборки мусора сложнее, чем простое вычитание.

Нагрузка на процессор трудно измерить в Java, я обычно придерживаюсь времени выполнения и оптимизирую более длинные / повторяющиеся разделы

С ThreadMXBean вы можете получить использование ЦП отдельных потоков и время процессора, а не время, которое может быть полезно.

Однако часто проще использовать профилировщик, так как этот процесс часто генерирует много данных, и вам нужен хороший инструмент визуализации, чтобы увидеть, что происходит.

Я использую Yourkit, так как мне легче решать проблемы, которые использовались другими профилировщиками. Я также использую встроенный hprof, так как это может дать вам другое представление о профиле вашего приложения (но не так полезно)

Использование Java Profiler - лучший вариант, и он даст вам всю необходимую информацию о коде. то есть время отклика, поток вызовов, использование памяти и т. д.

Я предложу вам JENSOR, Java Profiler с открытым исходным кодом, за его простоту использования и низкую нагрузку на процессор. Вы можете скачать его, установить код и получить всю необходимую информацию о вашем коде.

Вы можете скачать его с: http://jensor.sourceforge.net//

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

Для CPU вы можете получить его текущее значение:

OperatingSystemMXBean osBean = ManagementFactory.getPlatformMXBean(
            OperatingSystemMXBean.class); 
double processCpuLoad = osBean.getProcessCpuLoad();

Для памяти это можно сделать:

MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
int currentHeapUsedInMo = (int) (memoryMXBean.getHeapMemoryUsage().getUsed() / 1_000_000);

Что касается меры памяти, ожидание большого сбора данных перед выполнением метода повышает его надежность.

Например, может помочь что-то подобное:

import com.google.common.testing.GcFinalization;

GcFinalization.awaitFullGc();
foo.execute(); // method to execute

GcFinalizationпроисходит из тестовой библиотеки Guava.

У всего этого мало накладных расходов. Таким образом, идея состоит в сборе метрик (например, каждую секунду) для каждого вызванного метода, который вы хотите отслеживать, и, когда метод вернется, вычислить максимальное / среднее значение или любую полезную информацию для них.

Я бы предпочел, чтобы АОП сделал это.
Spring AOP - это простой и хороший способ создавать аспекты и устанавливать для них pointcut, но вы также можете сделать это с помощью AspectJ, если вам нужны некоторые конкретные вещи с точки зрения функций AOP.

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