Измерение времени выполнения 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?
Такие измерения предназначены для одноразовых сопоставлений производительности, и поэтому я не ищу никаких длительных процессов мониторинга в процессе производства.
Я более чем счастлив быть упомянутым в учебниках или внешних примерах и не ожидаю полного ответа здесь. Тем не менее, если что-либо столь же простое, как выше, может быть достигнуто, реалистичный пример будет очень хорошо снижаться.
Ответы
Ответ 1
Профилирование может быть более простым вариантом, так как вы не нуждаетесь в производственной статистике. Профилирование также не требует модификации кода. VisualVM (который поставляется с JDK 1.6.06+) - простой инструмент. Если вы хотите что-то более глубокое, я бы пошел с Eclipse TPTP, профилировщиком Netbeans или JProfiler (заплатил).
Если вы хотите написать свою собственную, рассмотрите следующее:
Простые измерения, такие как время выполнения, могут выполняться путем "синхронизации" интересующего вас раздела:
long start = System.nanoTime(); // requires java 1.5
// Segment to monitor
double elapsedTimeInSec = (System.nanoTime() - start) * 1.0e-9;
Вы можете использовать подобный метод для мониторинга памяти с помощью методов Runtime.getRuntime(). * memory(). Имейте в виду, что использование памяти отслеживания в среде сбора мусора более сложное, чем простое вычитание.
Загрузка процессора трудно измерить в Java, я обычно придерживаюсь времени выполнения и оптимизирую более длинные/повторяющиеся разделы
Ответ 2
С помощью ThreadMXBean вы можете использовать CPU для использования отдельных потоков и времени процессора, а не времени, которое может быть полезно.
Однако его часто проще использовать профилировщик, так как этот процесс часто генерирует много данных, и вам нужен хороший инструмент визуализации, чтобы увидеть, что происходит.
Я использую Yourkit, поскольку мне легче решать проблемы, которые использовали другие профилировщики.
Я также использую встроенный hprof, так как это может дать вам другое представление о профиле вашего приложения (но не так полезно)
Ответ 3
Использование Java Profiler - лучший вариант, и он даст вам все понимание, которое вам нужно в коде. viz Response Times, Thread CallTraces, Утилиты памяти и т.д.
Я предлагаю вам JENSOR, открытый Java-профайлер с открытым исходным кодом, для простоты использования и низкие накладные расходы на CPU. Вы можете загрузить его, использовать код и получить всю необходимую информацию о своем коде.
Вы можете скачать его из: http://jensor.sourceforge.net/
Ответ 4
Мы можем измерить процессор и память, используемые во время определенного вызванного метода, собирая показатели процессора и памяти во время его выполнения.
Конечно, если другие параллельные потоки для других методов потребляют память и процессор во время его выполнения, вы застряли. Так что это правильный подход, в то время как вы можете выполнять метод изолированным способом.
Для процессора вы можете получить его текущее значение:
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 - это простой и хороший способ создания аспектов и установки для них точечных ключей, но вы также можете сделать это с AspectJ, если вам нужны какие-то особые вещи с точки зрения возможностей AOP.