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

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

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

Ответы [ 37 ]

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

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

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

long duration = (endTime - startTime);  //divide by 1000000 to get milliseconds.
174 голосов
/ 08 октября 2008

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

long startTime = System.currentTimeMillis();

doReallyLongThing();

long endTime = System.currentTimeMillis();

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

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

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

162 голосов
/ 14 марта 2013

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

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 +

123 голосов
/ 02 февраля 2015

Использование Мгновенное и Продолжительность из нового API Java 8,

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

выходы,

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

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

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

73 голосов
/ 04 декабря 2015

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

Дата

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

Joda -время

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

API даты и времени Java из Java 8 «A 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]
36 голосов
/ 08 октября 2008

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

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

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

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

34 голосов
/ 06 апреля 2014

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

}
24 голосов
/ 26 ноября 2015

С 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<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;
    };
}
16 голосов
/ 03 декабря 2011

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