Как мне рассчитать время выполнения метода в Java?

834
  1. Как я могу получить время выполнения метода?
  2. Существует ли Timerслужебный класс для таких вещей, как время, сколько времени занимает задача и т. Д.?

Большинство запросов в Google возвращают результаты для таймеров, которые планируют потоки и задачи, а это не то, что мне нужно.

Огрский псалом33
источник
JAMon API - это бесплатный, простой, высокопроизводительный, поточно-ориентированный Java API, который позволяет разработчикам легко отслеживать производительность и масштабируемость производственных приложений. JAMon отслеживает хиты, время выполнения (общее, среднее, минимальное, максимальное, стандартное отклонение) и многое другое. http://jamonapi.sourceforge.net/ скачать: http://sourceforge.net/project/showfiles.php?group_id=96550
Майк Пон
1
Возможно, вы также захотите взглянуть на класс Apache Commons Lang StopWatch . Простой, но полезный служебный класс.
Позже похожий Вопрос: Как мне написать корректный микро-тест в Java?
Василий Бурк
Да, StopWatch отлично подходит для этого.
Шубхам Пандей
Java 8 с использованием Instantкласса: stackoverflow.com/a/30975902/1216775
akhil_mittal

Ответы:

1208

Всегда есть старомодный способ:

long startTime = System.nanoTime();
methodToTime();
long endTime = System.nanoTime();

long duration = (endTime - startTime);  //divide by 1000000 to get milliseconds.
дислокация
источник
234
на самом деле, это «модно», потому что вы использовали nanoTime, который не был добавлен до java5
Джон Гарднер
11
Это (или использование System.currentTimeMillis ()) похоже на то, как это обычно делается в Java ... что я видел в любом случае. Меня все еще слегка удивляет отсутствие встроенного класса, такого как Timer t = new Timer (); String s = t.getElapsed (format); и т. д.
Псалом 33 Огре
18
nanoTime не гарантирует точность лучше, чем currentTimeMillis (), хотя обычно это делает. forums.sun.com/thread.jspa?messageID=9460663 и simongbrown.com/blog/2007/08/20/…
Джеймс
10
Конечно, всегда важно помнить о подводных камнях микропроцессорного тестирования, таких как оптимизация компилятора / JVM, которая может исказить результат = 8-)
Yuval
18
Нет необходимости в блоке finally, так как endTime не будет использоваться, если выдается исключение.
Питер Лори
197

Я иду с простым ответом. Работает для меня.

long startTime = System.currentTimeMillis();

doReallyLongThing();

long endTime = System.currentTimeMillis();

System.out.println("That took " + (endTime - startTime) + " milliseconds");

Это работает довольно хорошо. Разрешение очевидно только с точностью до миллисекунды, вы можете сделать лучше с System.nanoTime (). Есть некоторые ограничения для обоих (срезы расписания операционной системы и т. Д.), Но это работает довольно хорошо.

В среднем за пару пробежек (чем больше, тем лучше), и вы получите достойную идею.

MBCook
источник
51
На самом деле, System.currentTimeMillis () имеет точность только выше 15 мс. Для действительно низких значений нельзя доверять. Решением для этого (как уже упоминалось) является System.nanoTime ();
Стив г
Хорошо, я собирался принять это как официальный ответ, пока не прочитал комментарий Стива Дж. Отличный лакомый кусочек, Стив!
Огрский псалом33
4
nanoTime () не гарантирует точность лучше, чем currentTimeMillis, но многие реализации JVM имеют большую точность с nanoTime.
Джеймс Шек
5
@JamesSchek Вам действительно нужно посмотреть свою формулировку, как я уже упоминал в этом идентичном комментарии в другом месте; nanoTimeгарантированно будет по крайней мере столь же решительным, как currentTimeMillis. docs.oracle.com/javase/7/docs/api/java/lang/…
b1nary.atr0phy
Одним небольшим преимуществом currentTimeMillisявляется то, что это фактическая временная метка, и она также может быть использована для регистрации времени начала / окончания, тогда как nanoTime«может использоваться только для измерения прошедшего времени и не связана с каким-либо другим понятием системного или настенного времени. «.
Брэд Паркс
177

Давайте, ребята! Никто не упомянул способ Гуавы сделать это (что, возможно, потрясающе):

import com.google.common.base.Stopwatch;

Stopwatch timer = Stopwatch.createStarted();
//method invocation
LOG.info("Method took: " + timer.stop());

Приятно то, что Stopwatch.toString () делает хорошую работу по выбору единиц времени для измерения. Т.е. если значение мало, оно выдаст 38 нс, если оно длинное, то покажет 5 м 3 с

Еще приятнее

Stopwatch timer = Stopwatch.createUnstarted();
for (...) {
   timer.start();
   methodToTrackTimeFor();
   timer.stop();
   methodNotToTrackTimeFor();
}
LOG.info("Method took: " + timer);

Примечание: Google Guava требует Java 1.6+

Дмитрий Калашников
источник
21
К сожалению, секундомер Гуавы не является поточно-ориентированным. я научился этому нелегко.
Декстер Легаспи
6
@DexterLegaspi Был бы очень заинтересован в вашем опыте! Заботиться, чтобы поделиться?
Сиддхартха
1
Параллельное использование секундомера приведет к тому, что вы будете звонить start()несколько раз подряд (то же самое для stop()).
Минвэй Самуил
141

Используя Instant и Duration из нового API Java 8,

Instant start = Instant.now();
Thread.sleep(5000);
Instant end = Instant.now();
System.out.println(Duration.between(start, end));

выходы,

PT5S
Суфиян Гори
источник
2
Спасибо, Как я могу вывести результат, не имея ПТ впереди?
java123999
1
Проблема метода заключается в том, что Instant не создает проблем с точностью до милли и нано секунд. Ref: stackoverflow.com/questions/20689055/...
prashantsunkari
8
@ java123999: Вы можете позвонить Duration.between(start, end).getSeconds(). Durationтакже есть методы для преобразования в другие единицы времени, например, toMillis()которые преобразуются в миллисекунды.
Эмиль Лунде
100

Собрались все возможные пути вместе в одном месте.

Свидание

Date startDate = Calendar.getInstance().getTime();
long d_StartTime = new Date().getTime();
Thread.sleep(1000 * 4);
Date endDate = Calendar.getInstance().getTime();
long d_endTime = new Date().getTime();
System.out.format("StartDate : %s, EndDate : %s \n", startDate, endDate);
System.out.format("Milli = %s, ( D_Start : %s, D_End : %s ) \n", (d_endTime - d_StartTime),d_StartTime, d_endTime);

Система. currentTimeMillis ()

long startTime = System.currentTimeMillis();
Thread.sleep(1000 * 4);
long endTime = System.currentTimeMillis();
long duration = (endTime - startTime);  
System.out.format("Milli = %s, ( S_Start : %s, S_End : %s ) \n", duration, startTime, endTime );
System.out.println("Human-Readable format : "+millisToShortDHMS( duration ) );

Удобочитаемый формат

public static String millisToShortDHMS(long duration) {
    String res = "";    // java.util.concurrent.TimeUnit;
    long days       = TimeUnit.MILLISECONDS.toDays(duration);
    long hours      = TimeUnit.MILLISECONDS.toHours(duration) -
                      TimeUnit.DAYS.toHours(TimeUnit.MILLISECONDS.toDays(duration));
    long minutes    = TimeUnit.MILLISECONDS.toMinutes(duration) -
                      TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(duration));
    long seconds    = TimeUnit.MILLISECONDS.toSeconds(duration) -
                      TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(duration));
    long millis     = TimeUnit.MILLISECONDS.toMillis(duration) - 
                      TimeUnit.SECONDS.toMillis(TimeUnit.MILLISECONDS.toSeconds(duration));

    if (days == 0)      res = String.format("%02d:%02d:%02d.%04d", hours, minutes, seconds, millis);
    else                res = String.format("%dd %02d:%02d:%02d.%04d", days, hours, minutes, seconds, millis);
    return res;
}

Guava: Google Stopwatch JAR «Цель секундомера - измерить прошедшее время в наносекундах.

com.google.common.base.Stopwatch g_SW = Stopwatch.createUnstarted();
g_SW.start();
Thread.sleep(1000 * 4);
g_SW.stop();
System.out.println("Google StopWatch  : "+g_SW);

Apache Commons Lang JAR « StopWatch предоставляет удобный API для таймингов.

org.apache.commons.lang3.time.StopWatch sw = new StopWatch();
sw.start();     
Thread.sleep(1000 * 4);     
sw.stop();
System.out.println("Apache StopWatch  : "+ millisToShortDHMS(sw.getTime()) );

ДЖОДА- ВРЕМЯ

public static void jodaTime() throws InterruptedException, ParseException{
    java.text.SimpleDateFormat ms_SDF = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");
    String start = ms_SDF.format( new Date() ); // java.util.Date

    Thread.sleep(10000);

    String end = ms_SDF.format( new Date() );       
    System.out.println("Start:"+start+"\t Stop:"+end);

    Date date_1 = ms_SDF.parse(start);
    Date date_2 = ms_SDF.parse(end);        
    Interval interval = new org.joda.time.Interval( date_1.getTime(), date_2.getTime() );
    Period period = interval.toPeriod(); //org.joda.time.Period

    System.out.format("%dY/%dM/%dD, %02d:%02d:%02d.%04d \n", 
        period.getYears(), period.getMonths(), period.getDays(),
        period.getHours(), period.getMinutes(), period.getSeconds(), period.getMillis());
}

Java date time API из Java 8 «Объект Duration представляет период времени между двумя объектами Instant .

Instant start = java.time.Instant.now();
    Thread.sleep(1000);
Instant end = java.time.Instant.now();
Duration between = java.time.Duration.between(start, end);
System.out.println( between ); // PT1.001S
System.out.format("%dD, %02d:%02d:%02d.%04d \n", between.toDays(),
        between.toHours(), between.toMinutes(), between.getSeconds(), between.toMillis()); // 0D, 00:00:01.1001 

Spring Framework предоставляетслужебный класс StopWatch для измерения прошедшего времени в Java.

StopWatch sw = new org.springframework.util.StopWatch();
sw.start("Method-1"); // Start a named task
    Thread.sleep(500);
sw.stop();

sw.start("Method-2");
    Thread.sleep(300);
sw.stop();

sw.start("Method-3");
    Thread.sleep(200);
sw.stop();

System.out.println("Total time in milliseconds for all tasks :\n"+sw.getTotalTimeMillis());
System.out.println("Table describing all tasks performed :\n"+sw.prettyPrint());

System.out.format("Time taken by the last task : [%s]:[%d]", 
        sw.getLastTaskName(),sw.getLastTaskTimeMillis());

System.out.println("\n Array of the data for tasks performed « Task Name: Time Taken");
TaskInfo[] listofTasks = sw.getTaskInfo();
for (TaskInfo task : listofTasks) {
    System.out.format("[%s]:[%d]\n", 
            task.getTaskName(), task.getTimeMillis());
}

Вывод:

Total time in milliseconds for all tasks :
999
Table describing all tasks performed :
StopWatch '': running time (millis) = 999
-----------------------------------------
ms     %     Task name
-----------------------------------------
00500  050%  Method-1
00299  030%  Method-2
00200  020%  Method-3

Time taken by the last task : [Method-3]:[200]
 Array of the data for tasks performed « Task Name: Time Taken
[Method-1]:[500]
[Method-2]:[299]
[Method-3]:[200]
Яши
источник
Секундомер Guava, Apache Commons и Spring Framework не являются поточно-ориентированными. Не безопасно для производственного использования.
Дипак Путрая
@DeepakPuthraya тогда какую библиотеку использовать, которая безопасна для производственного использования?
Гаурав
1
@DeepakPuthraya вы можете использовать Java 8, предоставляемый API даты и времени Java. Что просто.
Яш
IMO этот пост был бы полезен, если бы каждое решение также показывало результаты системных выходов.
BAERUS
87

Используйте профилировщик (JProfiler, Netbeans Profiler, Visual VM, Eclipse Profiler и т. Д.). Вы получите самые точные результаты и наименее навязчивый. Они используют встроенный механизм JVM для профилирования, который также может дать вам дополнительную информацию, такую ​​как трассировки стека, пути выполнения и более полные результаты, если это необходимо.

При использовании полностью интегрированного профилировщика профилировать метод очень просто. Щелкните правой кнопкой мыши, Profiler -> Добавить к корневым методам. Затем запустите профилировщик так же, как вы выполняли тестовый прогон или отладчик.

Джеймс Шек
источник
Это было также отличным предложением, и одним из тех «скучных» моментов лампочки для меня, когда я читал этот ответ. Наш проект использует JDeveloper, но я проверил, и, конечно же, у него есть встроенный профилировщик!
Огрский псалом33
2
От java 7 build 40 (я думаю) они включали в себя бывший регистратор полетов JRockits до java (поиск Java Mission Control)
Niels Bech Nielsen
Конечно же @NielsBechNielsen! oracle.com/technetwork/java/javaseproducts/mission-control/...
Ogre Psalm33
Как получить выполнение метода в Java на Visual VM, например?
okwap
41

Это, вероятно, не то, что вы хотели, чтобы я сказал, но это хорошее использование АОП. Обведите прокси-перехватчик вокруг вашего метода и определите время там.

К сожалению, вопрос «что, почему и как» в АОП выходит за рамки этого ответа, но я бы так и сделал.

Изменить: Вот ссылка на Spring AOP, чтобы начать, если вы заинтересованы. Это самая доступная реализация AOP, которую Iive встретил для Java.

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

skaffman
источник
3
Вот учебник о том, как это сделать с помощью Spring: veerasundar.com/blog/2010/01/…
Дэвид Тинкер,
39

System.currentTimeMillis();НЕ является хорошим подходом для измерения производительности ваших алгоритмов. Он измеряет общее время, которое вы испытываете, когда пользователь смотрит на экран компьютера. Он также включает время, затрачиваемое всем, что работает на вашем компьютере в фоновом режиме. Это может иметь огромное значение, если на вашей рабочей станции запущено много программ.

Правильный подход использует java.lang.managementпакет.

С http://nadeausoftware.com/articles/2008/03/java_tip_how_get_cpu_and_user_time_benchmarking веб-сайта:

  • «Время пользователя» - это время, потраченное на выполнение собственного кода вашего приложения.
  • «Системное время» - это время, потраченное на выполнение кода ОС от имени вашего приложения (например, для ввода-вывода).

getCpuTime() Метод дает вам сумму из них:

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;

public class CPUUtils {

    /** Get CPU time in nanoseconds. */
    public static long getCpuTime( ) {
        ThreadMXBean bean = ManagementFactory.getThreadMXBean( );
        return bean.isCurrentThreadCpuTimeSupported( ) ?
            bean.getCurrentThreadCpuTime( ) : 0L;
    }

    /** Get user time in nanoseconds. */
    public static long getUserTime( ) {
        ThreadMXBean bean = ManagementFactory.getThreadMXBean( );
        return bean.isCurrentThreadCpuTimeSupported( ) ?
            bean.getCurrentThreadUserTime( ) : 0L;
    }

    /** Get system time in nanoseconds. */
    public static long getSystemTime( ) {
        ThreadMXBean bean = ManagementFactory.getThreadMXBean( );
        return bean.isCurrentThreadCpuTimeSupported( ) ?
            (bean.getCurrentThreadCpuTime( ) - bean.getCurrentThreadUserTime( )) : 0L;
    }

}
TondaCZE
источник
4
Это, безусловно, хороший момент, когда «время пользователя» (время настенных часов) не всегда является хорошим показателем производительности, особенно в многопоточной программе.
Огрский псалом33
Это ответ, который я ищу.
Чжао Ган
30

С Java 8 вы можете сделать что-то подобное с любыми обычными методами :

Object returnValue = TimeIt.printTime(() -> methodeWithReturnValue());
//do stuff with your 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, например, чтобы печатать только время в DebugMode или что-то еще.

Если вы работаете с Function, вы можете сделать что-то вроде этого:

Function<Integer, Integer> yourFunction= (n) -> {
        return IntStream.range(0, n).reduce(0, (a, b) -> a + b);
    };

Integer returnValue = TimeIt.printTime2(yourFunction).apply(10000);
//do stuff with your returnValue

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;
    };
}
Стефан
источник
Это выглядит намного лучше, чем другие решения. Это ближе к Spring AOP, но легче, чем это. Правда Java 8 способ! +1 Спасибо!
Амит Кумар
Возможно, это выглядит хорошо для вас, потому что Стефан использует новые необычные функции Java. Но я думаю, что это трудно понять и понять.
Кот Стимпсона
18

Также мы можем использовать класс StopWatch Apache Commons для измерения времени.

Образец кода

org.apache.commons.lang.time.StopWatch sw = new org.apache.commons.lang.time.StopWatch();

System.out.println("getEventFilterTreeData :: Start Time : " + sw.getTime());
sw.start();

// Method execution code

sw.stop();
System.out.println("getEventFilterTreeData :: End Time : " + sw.getTime());
Нараян
источник
15

Небольшой поворот, если вы не используете инструментарий и хотите использовать методы с малым временем выполнения: выполняйте его много раз, каждый раз удваивая число выполнений, пока не достигнете секунды, или около того. Таким образом, время обращения к System.nanoTime и т. Д., А также точность System.nanoTime не сильно влияют на результат.

    int runs = 0, runsPerRound = 10;
    long begin = System.nanoTime(), end;
    do {
        for (int i=0; i<runsPerRound; ++i) timedMethod();
        end = System.nanoTime();
        runs += runsPerRound;
        runsPerRound *= 2;
    } while (runs < Integer.MAX_VALUE / 2 && 1000000000L > end - begin);
    System.out.println("Time for timedMethod() is " + 
        0.000000001 * (end-begin) / runs + " seconds");

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

Ханс-Петер Стёрр
источник
13

Для этой цели мы используем аннотации AspectJ и Java. Если нам нужно узнать время выполнения метода, мы просто аннотируем его. Более продвинутая версия может использовать собственный уровень журнала, который можно включать и отключать во время выполнения.

public @interface Trace {
  boolean showParameters();
}

@Aspect
public class TraceAspect {
  [...]
  @Around("tracePointcut() && @annotation(trace) && !within(TraceAspect)")
  public Object traceAdvice ( ProceedingJintPoint jP, Trace trace ) {

    Object result;
    // initilize timer

    try { 
      result = jp.procced();
    } finally { 
      // calculate execution time 
    }

    return result;
  }
  [...]
}

источник
13

JEP 230: набор микробенчмарков

К вашему сведению, JEP 230: Microbenchmark Suite является проектом OpenJDK для:

Добавьте базовый набор микробенчмарков в исходный код JDK и упростите разработчикам запуск существующих микробенчмарков и создание новых.

Эта функция появилась в Java 12 .

Java Microbenchmark Harness (JMH)

Для более ранних версий Java взгляните на проект Java Microbenchmark Harness (JMH), на котором основан JEP 230.

Базилик Бурк
источник
11

Действительно хороший код.

http://www.rgagnon.com/javadetails/java-0585.html

import java.util.concurrent.TimeUnit;

long startTime = System.currentTimeMillis();
........
........
........
long finishTime = System.currentTimeMillis();

String diff = millisToShortDHMS(finishTime - startTime);


  /**
   * converts time (in milliseconds) to human-readable format
   *  "<dd:>hh:mm:ss"
   */
  public static String millisToShortDHMS(long duration) {
    String res = "";
    long days  = TimeUnit.MILLISECONDS.toDays(duration);
    long hours = TimeUnit.MILLISECONDS.toHours(duration)
                   - TimeUnit.DAYS.toHours(TimeUnit.MILLISECONDS.toDays(duration));
    long minutes = TimeUnit.MILLISECONDS.toMinutes(duration)
                     - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(duration));
    long seconds = TimeUnit.MILLISECONDS.toSeconds(duration)
                   - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(duration));
    if (days == 0) {
      res = String.format("%02d:%02d:%02d", hours, minutes, seconds);
    }
    else {
      res = String.format("%dd%02d:%02d:%02d", days, hours, minutes, seconds);
    }
    return res;
  }
айсберг
источник
3
На самом деле вопрос заключался в том, как рассчитать количество времени, которое занимает метод, а не в том, как его отформатировать. Однако этот вопрос довольно старый (почти четыре года!). Старайтесь не воскрешать старые темы, если ответ не добавит что-то новое и существенное поверх существующих ответов.
Ли
1
И чтобы добавить оставшиеся миллисы в конец, внесите следующие изменения: long millis = TimeUnit.MILLISECONDS.toMillis(duration) - TimeUnit.SECONDS.toMillis(TimeUnit.MILLISECONDS.toSeconds(duration)); if (days == 0) { res = String.format("%02d:%02d:%02d.%02d", hours, minutes, seconds, millis); } else { res = String.format("%dd%02d:%02d:%02d.%02d", days, hours, minutes, seconds, millis); }
Рик Баркхаус
10

Вы можете использовать Perf4j . Очень крутая утилита. Простое использование

String watchTag = "target.SomeMethod";
StopWatch stopWatch = new LoggingStopWatch(watchTag);
Result result = null; // Result is a type of a return value of a method
try {
    result = target.SomeMethod();
    stopWatch.stop(watchTag + ".success");
} catch (Exception e) {
    stopWatch.stop(watchTag + ".fail", "Exception was " + e);
    throw e; 
}

Более подробную информацию можно найти в Руководстве разработчика

Изменить: Проект кажется мертвым

mergenchik
источник
1
Perf4j также может генерировать хорошую статистику .
Пааске
8
new Timer(""){{
    // code to time 
}}.timeMe();



public class Timer {

    private final String timerName;
    private long started;

    public Timer(String timerName) {
        this.timerName = timerName;
        this.started = System.currentTimeMillis();
    }

    public void timeMe() {
        System.out.println(
        String.format("Execution of '%s' takes %dms.", 
                timerName, 
                started-System.currentTimeMillis()));
    }

}
Maciek Kreft
источник
1
Свернуть свой собственный простой класс - хороший выбор, когда у вас уже есть настроенная система сборки и зависимый OTS, и вы не хотите тратить время на добавление другого пакета OTS, который включает класс служебного таймера.
Огр Псалом 33
7

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

Если JIT решит скомпилировать его, ваши цифры будут сильно различаться. так что просто знайте

Люк
источник
7

Используя AOP / AspectJ и @Loggableаннотации из jcabi-aspect, вы можете сделать это легко и компактно:

@Loggable(Loggable.DEBUG)
public String getSomeResult() {
  // return some value
}

Каждый вызов этого метода будет отправляться в средство ведения журнала SLF4J с DEBUGуровнем ведения журнала. И каждое сообщение журнала будет включать время выполнения.

yegor256
источник
7

Spring предоставляет служебный класс org.springframework.util.StopWatch в соответствии с JavaDoc:

Простой секундомер, позволяющий рассчитывать время выполнения ряда задач, отображая общее время выполнения и время выполнения для каждой названной задачи.

Применение:

StopWatch stopWatch = new StopWatch("Performance Test Result");

stopWatch.start("Method 1");
doSomething1();//method to test
stopWatch.stop();

stopWatch.start("Method 2");
doSomething2();//method to test
stopWatch.stop();

System.out.println(stopWatch.prettyPrint());

Вывод:

StopWatch 'Performance Test Result': running time (millis) = 12829
-----------------------------------------
ms     %     Task name
-----------------------------------------
11907  036%  Method 1
00922  064%  Method 2

С аспектами:

@Around("execution(* my.package..*.*(..))")
public Object logTime(ProceedingJoinPoint joinPoint) throws Throwable {
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    Object retVal = joinPoint.proceed();
    stopWatch.stop();
    log.info(" execution time: " + stopWatch.getTotalTimeMillis() + " ms");
    return retVal;
}
Сунил Манхери
источник
Можно ли использовать это с AspectJ?
Зигимантус
7

Я написал метод для печати времени выполнения метода в удобочитаемой форме. Например, чтобы вычислить факториал в 1 миллион, потребуется приблизительно 9 минут. Таким образом, время выполнения печатается как:

Execution Time: 9 Minutes, 36 Seconds, 237 MicroSeconds, 806193 NanoSeconds

Код здесь:

public class series
{
    public static void main(String[] args)
    {
        long startTime = System.nanoTime();

        long n = 10_00_000;
        printFactorial(n);

        long endTime = System.nanoTime();
        printExecutionTime(startTime, endTime);

    }

    public static void printExecutionTime(long startTime, long endTime)
    {
        long time_ns = endTime - startTime;
        long time_ms = TimeUnit.NANOSECONDS.toMillis(time_ns);
        long time_sec = TimeUnit.NANOSECONDS.toSeconds(time_ns);
        long time_min = TimeUnit.NANOSECONDS.toMinutes(time_ns);
        long time_hour = TimeUnit.NANOSECONDS.toHours(time_ns);

        System.out.print("\nExecution Time: ");
        if(time_hour > 0)
            System.out.print(time_hour + " Hours, ");
        if(time_min > 0)
            System.out.print(time_min % 60 + " Minutes, ");
        if(time_sec > 0)
            System.out.print(time_sec % 60 + " Seconds, ");
        if(time_ms > 0)
            System.out.print(time_ms % 1E+3 + " MicroSeconds, ");
        if(time_ns > 0)
            System.out.print(time_ns % 1E+6 + " NanoSeconds");
    }
}
Пратик Патил
источник
6

Есть несколько способов сделать это. Я обычно использую что-то вроде этого:

long start = System.currentTimeMillis();
// ... do something ...
long end = System.currentTimeMillis();

или то же самое с System.nanoTime ();

Для чего-то большего на стороне бенчмаркинга, кажется, есть и такой: http://jetm.void.fm/ Никогда не пробовал.

Хорст Гутманн
источник
6

Вы можете использовать библиотеку метрик, которая предоставляет различные измерительные приборы. Добавить зависимость:

<dependencies>
    <dependency>
        <groupId>io.dropwizard.metrics</groupId>
        <artifactId>metrics-core</artifactId>
        <version>${metrics.version}</version>
    </dependency>
</dependencies>

И настроить его для вашей среды.

Методы могут быть аннотированы с помощью @Timed :

@Timed
public void exampleMethod(){
    // some code
}

или кусок кода, завернутый с таймером :

final Timer timer = metricsRegistry.timer("some_name");
final Timer.Context context = timer.time();
// timed code
context.stop();

Агрегированные метрики могут быть экспортированы в консоль, JMX, CSV или другие.

@Timed пример вывода метрик:

com.example.ExampleService.exampleMethod
             count = 2
         mean rate = 3.11 calls/minute
     1-minute rate = 0.96 calls/minute
     5-minute rate = 0.20 calls/minute
    15-minute rate = 0.07 calls/minute
               min = 17.01 milliseconds
               max = 1006.68 milliseconds
              mean = 511.84 milliseconds
            stddev = 699.80 milliseconds
            median = 511.84 milliseconds
              75% <= 1006.68 milliseconds
              95% <= 1006.68 milliseconds
              98% <= 1006.68 milliseconds
              99% <= 1006.68 milliseconds
            99.9% <= 1006.68 milliseconds
Как только
источник
5

Если вы хотите настенные часы

long start_time = System.currentTimeMillis();
object.method();
long end_time = System.currentTimeMillis();
long execution_time = end_time - start_time;
Дэвид Неем
источник
5

Как сказал «skaffman», используйте AOP ИЛИ вы можете использовать время выполнения байт-кода, точно так же, как инструменты покрытия метода модульного теста используют для прозрачного добавления информации о синхронизации к вызываемым методам.

Вы можете посмотреть на код, используемый инструментами с открытым исходным кодом, такими как Эмма ( http://downloads.sourceforge.net/emma/emma-2.0.5312-src.zip?modtime=1118607545&big_mirror=0 ). Другим инструментом покрытия с открытым исходным кодом является http://prdownloads.sourceforge.net/cobertura/cobertura-1.9-src.zip?download .

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

anjanb
источник
4
long startTime = System.currentTimeMillis();
// code goes here
long finishTime = System.currentTimeMillis();
long elapsedTime = finishTime - startTime; // elapsed time in milliseconds
Райан Родемойер
источник
4

Я изменил код из правильного ответа, чтобы получить результат в считанные секунды:

long startTime = System.nanoTime();

methodCode ...

long endTime = System.nanoTime();
double duration = (double)(endTime - startTime) / (Math.pow(10, 9));
Log.v(TAG, "MethodName time (s) = " + duration);
Денис Кутлубаев
источник
4

Вы можете использовать класс секундомера из основного проекта Spring:

Код:

StopWatch stopWatch = new StopWatch()
stopWatch.start();  //start stopwatch
// write your function or line of code.
stopWatch.stop();  //stop stopwatch
stopWatch.getTotalTimeMillis() ; ///get total time

Документация для секундомера: простой секундомер, позволяющий рассчитывать время выполнения ряда задач, показывая общее время выполнения и время выполнения для каждой названной задачи. Скрывает использование System.currentTimeMillis (), улучшая читабельность кода приложения и уменьшая вероятность ошибок вычислений. Обратите внимание, что этот объект не предназначен для работы с потоками и не использует синхронизацию. Этот класс обычно используется для проверки производительности во время проверки концепции и при разработке, а не как часть производственных приложений.

правин джайн
источник
3

Вы можете попробовать этот способ, если просто хотите знать время.

long startTime = System.currentTimeMillis();
//@ Method call
System.out.println("Total time [ms]: " + (System.currentTimeMillis() - startTime));    
gifpif
источник
3

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

public class Stopwatch {
    static long startTime;
    static long splitTime;
    static long endTime;

    public Stopwatch() {
        start();
    }

    public void start() {
        startTime = System.currentTimeMillis();
        splitTime = System.currentTimeMillis();
        endTime = System.currentTimeMillis();
    }

    public void split() {
        split("");
    }

    public void split(String tag) {
        endTime = System.currentTimeMillis();
        System.out.println("Split time for [" + tag + "]: " + (endTime - splitTime) + " ms");
        splitTime = endTime;
    }

    public void end() {
        end("");
    }
    public void end(String tag) {
        endTime = System.currentTimeMillis();
        System.out.println("Final time for [" + tag + "]: " + (endTime - startTime) + " ms");
    }
}

Пример использования:

public static Schedule getSchedule(Activity activity_context) {
        String scheduleJson = null;
        Schedule schedule = null;
/*->*/  Stopwatch stopwatch = new Stopwatch();

        InputStream scheduleJsonInputStream = activity_context.getResources().openRawResource(R.raw.skating_times);
/*->*/  stopwatch.split("open raw resource");

        scheduleJson = FileToString.convertStreamToString(scheduleJsonInputStream);
/*->*/  stopwatch.split("file to string");

        schedule = new Gson().fromJson(scheduleJson, Schedule.class);
/*->*/  stopwatch.split("parse Json");
/*->*/  stopwatch.end("Method getSchedule"); 
    return schedule;
}

Пример вывода на консоль:

Split time for [file to string]: 672 ms
Split time for [parse Json]: 893 ms
Final time for [get Schedule]: 1565 ms
msysmilu
источник
3

В Java 8 представлен новый класс с именем Instant. Согласно документу:

Мгновенное представляет начало наносекунды на временной шкале. Этот класс полезен для генерации метки времени для представления машинного времени. Диапазон мгновенного требует хранения числа больше, чем long. Чтобы достичь этого, класс хранит длинную, представляющую эпоху-секунды, и int, представляющий наносекунду секунды, которая всегда будет между 0 и 999 999 999. Время в секундах измеряется из стандартной эпохи Java 1970-01-01T00: 00: 00Z, где моменты после эпохи имеют положительные значения, а более ранние моменты имеют отрицательные значения. Как для частей с эпохой, так и для наносекунды, большее значение всегда на временной шкале всегда позже, чем меньшее значение.

Это можно использовать как:

Instant start = Instant.now();
try {
    Thread.sleep(7000);
} catch (InterruptedException e) {
    e.printStackTrace();
}
Instant end = Instant.now();
System.out.println(Duration.between(start, end));

Это печатает PT7.001S.

akhil_mittal
источник