Как мне рассчитать время выполнения метода в Java? - PullRequest
757 голосов
/ 08 октября 2008

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

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

Ответы [ 37 ]

14 голосов
/ 05 ноября 2008

Небольшой поворот, если вы не используете инструментарий и хотите рассчитывать методы с малым временем выполнения: выполняйте его много раз, каждый раз удваивая число выполнений, пока не достигнете секунды, или около того. Таким образом, время обращения к 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-компилятор выполняет свою работу, а затем повторяет этот тест несколько раз и принимает самое низкое время выполнения.

12 голосов
/ 08 октября 2008

Для этой цели мы используем аннотации 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;
  }
  [...]
}
10 голосов
/ 15 июня 2012

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

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;
  }
9 голосов
/ 02 июля 2016

JEP 230: Microbenchmark Suite

FYI, JEP 230: Microbenchmark Suite - это OpenJDK проект для:

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

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

Жгут проводов Java Microbenchmark (JMH)

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

7 голосов
/ 03 апреля 2013
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()));
    }

}
7 голосов
/ 26 февраля 2012

Вы можете использовать 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; 
}

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

Редактировать: Проект кажется мертвым

6 голосов
/ 08 октября 2008

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

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

6 голосов
/ 07 января 2013

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

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

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

5 голосов
/ 08 октября 2008

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

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

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

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

5 голосов
/ 29 октября 2018

Я написал метод для печати времени выполнения метода в удобочитаемой форме. Например, чтобы вычислить факториал в 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");
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...