Измерение времени выполнения 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.