Подтвердить что ты не робот

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

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

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

4b9b3361

Ответ 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.