Как измерить время выполнения метода в Java?
Как получить время выполнения метода?
Существует ли класс утилита Timer
для измерения времени выполнения задач и т.д.?
Большинство поисковых запросов в Google возвращают результаты, связанные с таймерами, которые планируют потоки и задачи, что не соответствует моим потребностям.
5 ответ(ов)
Существует всегда старомодный способ:
long startTime = System.nanoTime();
методДляЗамераВремени();
long endTime = System.nanoTime();
long duration = (endTime - startTime); // разделите на 1000000, чтобы получить миллисекунды.
Этот код позволяет измерить время выполнения метода, используя наносекунды в качестве единицы измерения. Просто помните, что для получения времени в миллисекундах нужно разделить разницу на 1,000,000.
Я выберу простой ответ. Это работает для меня.
long startTime = System.currentTimeMillis();
doReallyLongThing();
long endTime = System.currentTimeMillis();
System.out.println("Это заняло " + (endTime - startTime) + " миллисекунд");
Это работает довольно хорошо. Разрешение, конечно, ограничено миллисекундами, так что вы можете получить лучшие результаты с помощью System.nanoTime()
. Есть некоторые ограничения у обоих методов (например, планирование в операционной системе), но в целом это вполне подходит.
Среднее значение по нескольким запускам (чем больше, тем лучше) даст вам неплохое представление о времени выполнения.
Используйте профайлер (например, JProfiler, Netbeans Profiler, Visual VM, Eclipse Profiler и т.д.). Это даст вам наиболее точные результаты и будет наименее навязчивым способом. Они используют встроенный механизм JVM для профилирования, что также может предоставить дополнительную информацию, такую как стек вызовов, пути выполнения и более подробные результаты при необходимости.
При использовании полностью интегрированного профайлера профилировать метод довольно просто. Кликните правой кнопкой мыши, выберите Профайлер → Добавить в корневые методы. Затем запустите профайлер так же, как вы бы делали это во время тестового прогона или отладки.
С Java 8 вы можете сделать что-то подобное для любых нормальных методов:
Object returnValue = TimeIt.printTime(() -> methodWithReturnValue());
// выполняем действия с вашим returnValue
с классом TimeIt следующим образом:
public class TimeIt {
public static <T> T printTime(Callable<T> task) {
T call = null;
try {
long startTime = System.currentTimeMillis();
call = task.call();
System.out.print((System.currentTimeMillis() - startTime) / 1000d + "s");
} catch (Exception e) {
//...
}
return call;
}
}
С помощью этого метода вы можете легко измерять время выполнения в любом месте вашего кода, не нарушая его структуру. В этом простом примере я просто вывожу время. Вы можете добавить переключатель для TimeIt, чтобы, например, выводить время только в режиме отладки или что-то подобное.
Если вы работаете с Function, вы можете сделать что-то подобное:
Function<Integer, Integer> yourFunction = (n) -> {
return IntStream.range(0, n).reduce(0, (a, b) -> a + b);
};
Integer returnValue = TimeIt.printTime2(yourFunction).apply(10000);
// выполняем действия с вашим returnValue
А метод printTime2
можно реализовать так:
public static <T, R> Function<T, R> printTime2(Function<T, R> task) {
return (t) -> {
long startTime = System.currentTimeMillis();
R apply = task.apply(t);
System.out.print((System.currentTimeMillis() - startTime) / 1000d + "s");
return apply;
};
}
Этот код также позволяет измерять время выполнения функций в Java, что делает его весьма удобным для профилирования.
Вы также можете использовать класс StopWatch
из библиотеки Apache Commons для измерения времени.
Пример кода:
org.apache.commons.lang.time.StopWatch sw = new org.apache.commons.lang.time.StopWatch();
System.out.println("getEventFilterTreeData :: Время начала : " + sw.getTime());
sw.start();
// Код выполнения метода
sw.stop();
System.out.println("getEventFilterTreeData :: Время окончания : " + sw.getTime());
Такой подход позволяет вам легко отслеживать время выполнения определённых участков кода. Убедитесь, что у вас подключена библиотека Apache Commons в вашем проекте, чтобы использовать этот класс.
Как работают сервлеты? Инстанцирование, сессии, общие переменные и многопоточность
Разница между StringBuilder и StringBuffer
Java 8: Преобразование List<V> в Map<K, V>
Возможные значения конфигурации hbm2ddl.auto в Hibernate и их назначение
Что такое PECS (Producer Extends Consumer Super)?