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

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

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

30 ответов


всегда по-старинке:

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

long duration = (endTime - startTime);  //divide by 1000000 to get milliseconds.

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

long startTime = System.currentTimeMillis();

doReallyLongThing();

long endTime = System.currentTimeMillis();

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

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

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


ребята! Никто не упоминал гуавы способ сделать это (что, бесспорно, офигенно):

import com.google.common.base.Stopwatch;

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

хорошая вещь, что секундомер.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+


используя МиГ и продолжительность из нового API Java 8,

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

выходы

PT5S

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

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


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

дата

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;
}

Гуава: Google секундомер 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 "секундомер предоставляет удобный 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 дата время API от Java 8 " A продолжительность


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

что, почему и как AOP довольно выходит за рамки этого ответа, к сожалению, но это то, как я, вероятно, это сделаю.

Edit:вот ссылка Весна AOP, чтобы вы начали, если вы заинтересованы. Это самая доступная реализация AOP, с которой сталкивается Iive Ява.

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


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;
    }

}

С 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;
}
}

С помощью этого methode вы можете легко измерять время в любом месте вашего кода, не нарушая его. В этом простом примере я просто печатаю время. Можете ли вы добавить переключатель для TimeIt, например, только для печати времени в DebugMode или что-то еще.

Если вы работаете с функции вы можете сделать что-то вроде это:

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;
    };
}

также мы можем использовать класс секундомера 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());

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


для этой цели мы используем аннотации 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;
  }
  [...]
}

очень хороший код.

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;
  }

JEP 230: Microbenchmark Suite

кстати, JEP 230: Microbenchmark Suite это OpenJDK


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()));
    }

}

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

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

изменить: кажется, умер


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

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

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


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

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


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

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

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

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


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

long start_time = System.currentTimeMillis();
object.method();
long end_time = System.currentTimeMillis();
long execution_time = end_time - start_time;

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

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

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


Spring предоставляет служебный класс org.springframework.утиль.Секундомер, согласно 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;
}

long startTime = System.currentTimeMillis();
// code goes here
long finishTime = System.currentTimeMillis();
long elapsedTime = finishTime - startTime; // elapsed time in milliseconds

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

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);

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

long startTime = System.currentTimeMillis();
//@ Method call
System.out.println("Total time [ms]: " + (System.currentTimeMillis() - startTime));    

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

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

в Java 8 новый класс с именем это. Согласно doc:

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

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

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.


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

<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

System.nanoTime() - довольно точная системная утилита для измерения времени выполнения. Но будьте осторожны, если вы работаете в режиме упреждающего планировщика (по умолчанию), эта утилита фактически измеряет время настенных часов, а не время процессора. Таким образом можно заметить различные значения времени выполнения от запуска до запуска, в зависимости от загрузки системы. Если вы ищете время процессора, я думаю, что запуск вашей программы в режиме реального времени сделает трюк. Вы должны использовать RT linux. ссылка:программирование в реальном времени с В Linux


измерения производительности на моей машине

  • система.nanoTime() : 750ns
  • система.currentTimeMillis() : 18ns

Как уже упоминалось, система.считается, что nanoTime() измеряет прошедшее время. Просто имейте в виду стоимость, если используется insied цикл или тому подобное.