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


85

Как вы рассчитываете время выполнения Java-программы? Я не уверен, какой класс мне следует использовать для этого.

Я как бы ищу что-то вроде:

// Some timer starts here
for (int i = 0; i < length; i++) {
  // Do something
}
// End timer here

System.out.println("Total execution time: " + totalExecutionTime);

Ответы:


139
final long startTime = System.currentTimeMillis();
for (int i = 0; i < length; i++) {
  // Do something
}
final long endTime = System.currentTimeMillis();

System.out.println("Total execution time: " + (endTime - startTime));

2
на самом деле это должно быть nanoTime
Евгений

6
Не должно быть nanoTime. См. Ответ Ру.
fabspro

4
Есть ли какая-то особая причина, по которой вы использовали здесь слово «final»? Что изменилось бы, если бы вы опустили это ключевое слово?
dijxtra

9
Использование @dijxtra finalимеет то преимущество, что вы не можете случайно назначить его (а также другие преимущества, такие как анонимный доступ к классам и т. д.). В этом коде это не имело бы значения. Довольно распространенная практика - все делать finalи finalунифицировать только в случае необходимости.
wchargin

1
Тестируемый код вместе с измерениями времени следует запускать несколько раз, а первый результат следует отбросить. Первый, вероятно, будет включать время загрузки класса и т. Д. Запустив его несколько раз, вы, конечно же, получите среднее значение, которое будет более полезным и надежным.
Арун Рамакришнан

34

Имейте в виду, что есть некоторые проблемы, когда System#nanoTime()их нельзя надежно использовать на многоядерных процессорах для записи прошедшего времени ... каждое ядро ​​поддерживает свой собственный TSC ( счетчик отметок времени ): этот счетчик используется для получения нано-времени (на самом деле это количество тиков с момента загрузки ЦП).

Следовательно, если ОС не выполняет некоторую деформацию времени TSC, чтобы синхронизировать ядра, тогда, если поток планируется на одном ядре, когда выполняется начальное считывание времени, а затем переключается на другое ядро, относительное время может спорадически перемещаться назад и вперед.

Я наблюдал это некоторое время назад на AMD / Solaris, где время, прошедшее между двумя временными точками, иногда возвращалось либо как отрицательные значения, либо как неожиданно большие положительные числа. Для принудительной установки AMD PowerNow! Требовались патч ядра Solaris и настройки BIOS. off, который, похоже, решил эту проблему.

Кроме того, есть (AFAIK) пока еще не исправленная ошибка при использовании java System#nanoTime()в среде VirtualBox; вызывая для нас всевозможные причудливые периодические проблемы с потоками, поскольку большая часть java.util.concurrencyпакета полагается на нано-время.

Смотрите также:

System.nanoTime () совершенно бесполезен? http://vbox.innotek.de/pipermail/vbox-trac/2010-January/135631.html


9

Вы получаете текущее системное время в миллисекундах:

final long startTime = System.currentTimeMillis();

Затем вы делаете то, что собираетесь делать:

for (int i = 0; i < length; i++) {
  // Do something
}

Тогда вы увидите, сколько времени это заняло:

final long elapsedTimeMillis = System.currentTimeMillis() - startTime;

Ответ BalusC также верен; это зависит от необходимого разрешения таймера и от того, зачем вам это время.
Джонатан Файнберг,

9

Вы можете использовать System#nanoTime(). Получите это до и после казни и просто посчитайте. Предпочтительно вышеSystem#currentTimeMillis() потому что он обеспечивает лучшую точность. В зависимости от используемого оборудования и платформы, вы можете получить неправильный промежуток времени. Здесь, с Core2Duo в Windows, между 0 и ~ 15 мс фактически ничего нельзя вычислить.

Более продвинутый инструмент - профилировщик .


Таймер в Windows по умолчанию не имеет особенно хорошего разрешения. Также есть высокопроизводительный таймер, но его намного сложнее использовать даже из C, а Java (AFAIK) не предоставляет доступ к такому низкому уровню хакерства без JNI thunk.
Donal Fellows,

1
nanoTime()есть одна проблема (по крайней мере, в Windows); метка времени зависит от ядра процессора. У меня была программа, которая имела отрицательное время выполнения, потому что у нее была временная метка «старта» на одном ядре и временная метка «остановки» на другом ядре.
gustafc

3

Для простых вещей может работать System.currentTimeMillis () .

На самом деле это настолько распространено, что моя IDE настроена так, что при вводе «t0» она генерирует следующую строку:

final long t0 = System.currentTimeMillis()

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

http://perf4j.codehaus.org/devguide.html


+1 за указание кода автогенератора. Я все время использую подобное утверждение и не знал о вставке шаблонов кода. Только что узнал, как это сделать с помощью eclipse, и это определенно поможет!
Джейсон

Все услуги Codehaus прекращены. Ваша ссылка теперь не работает.
naXa 06

2

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

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

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


2

Вот несколько способов узнать время выполнения в Java:

1) System.nanoTime ()

long startTime = System.nanoTime();
.....your code....
long endTime   = System.nanoTime();
long totalTime = endTime - startTime;
System.out.println("Execution time in nanoseconds  : " + totalTime);
System.out.println("Execution time in milliseconds : " + totalTime / 1000000);

2) System.currentTimeMillis ()

long startTime = System.currentTimeMillis();
.....your code....
long endTime = System.currentTimeMillis();
long totalTime = endTime - startTime;
System.out.println("Execution time in milliseconds  : " + totalTime);

3) Instant.now ()

long startTime = Instant.now().toEpochMilli();
.....your code....
long endTime = Instant.now().toEpochMilli();
long totalTime = endTime - startTime;
System.out.println("Execution time in milliseconds: " + totalTime);

или же

Instant start = Instant.now();
.....your code....
Instant end = Instant.now();
Duration interval = Duration.between(start, end);
System.out.println("Execution time in seconds: " +interval.getSeconds());

4) Date.getTime ()

long startTime = new Date().getTime();
.....your code....
long endTime = new Date().getTime();
long totalTime = endTime - startTime;
System.out.println("Execution time in milliseconds: " + totalTime);

1

используйте long startTime=System.currentTimeMillis()для времени начала, в верхней части цикла

положить long endTime= System.currentTimeMillis();за пределы конца петли. Вам нужно будет вычесть значения, чтобы получить время выполнения в миллисекундах.

Если вам нужно время в наносекундах, посмотрите System.nanoTime()


1

Я создал функцию более высокого порядка, которая принимает код, который вы хотите измерить, в / как лямбда:

class Utils {

    public static <T> T timeIt(String msg, Supplier<T> s) {
        long startTime = System.nanoTime();
        T t = s.get();
        long endTime = System.nanoTime();
        System.out.println(msg + ": " + (endTime - startTime) + " ns");
        return t;
    }

    public static void timeIt(String msg, Runnable r) {
       timeIt(msg, () -> {r.run(); return null; });
    }
}

Назовите это так:

Utils.timeIt("code 0", () ->
        System.out.println("Hallo")
);

// in case you need the result of the lambda
int i = Utils.timeIt("code 1", () ->
        5 * 5
);

Вывод:

код 0: 180528 нс
код 1: 12003 нс

Особая благодарность Энди Тернеру, который помог мне сократить избыточность. Смотрите здесь .



0

Вы также можете попробовать Perf4J. Это изящный способ делать то, что вы ищете, и помогает в агрегированной статистике производительности, такой как среднее, минимальное, максимальное, стандартное отклонение и количество транзакций в секунду за заданный промежуток времени. Выдержка из http://perf4j.codehaus.org/devguide.html :

StopWatch stopWatch = new LoggingStopWatch();

try {
    // the code block being timed - this is just a dummy example
    long sleepTime = (long)(Math.random() * 1000L);
    Thread.sleep(sleepTime);
    if (sleepTime > 500L) {
        throw new Exception("Throwing exception");
    }

    stopWatch.stop("codeBlock2.success", "Sleep time was < 500 ms");
} catch (Exception e) {
    stopWatch.stop("codeBlock2.failure", "Exception was: " + e);
}

Вывод:

INFO: start[1230493236109] time[447] tag[codeBlock2.success] message[Sleep time was < 500 ms]
INFO: start[1230493236719] time[567] tag[codeBlock2.failure] message[Exception was: java.lang.Exception: Throwing exception]
INFO: start[1230493237286] time[986] tag[codeBlock2.failure] message[Exception was: java.lang.Exception: Throwing exception]
INFO: start[1230493238273] time[194] tag[codeBlock2.success] message[Sleep time was < 500 ms]
INFO: start[1230493238467] time[463] tag[codeBlock2.success] message[Sleep time was < 500 ms]
INFO: start[1230493238930] time[310] tag[codeBlock2.success] message[Sleep time was < 500 ms]
INFO: start[1230493239241] time[610] tag[codeBlock2.failure] message[Exception was: java.lang.Exception: Throwing exception]
INFO: start[1230493239852] time[84] tag[codeBlock2.success] message[Sleep time was < 500 ms]
INFO: start[1230493239937] time[30] tag[codeBlock2.success] message[Sleep time was < 500 ms]
INFO: start[1230493239968] time[852] tag[codeBlock2.failure] message[Exception was: java.lang.Exception: Throwing exception]

0
public class someClass
{
   public static void main(String[] args) // your app start point
   {
       long start = java.util.Calendar.getInstance().getTimeInMillis();

       ... your stuff ...

       long end = java.util.Calendar.getInstance().getTimeInMillis();
       System.out.println("it took this long to complete this stuff: " + (end - start) + "ms");
   }
}

0

Использование System.currentTimeMillis () - правильный способ сделать это. Но если вы используете командную строку и хотите приблизительно и быстро рассчитать время всей программы, подумайте о следующем:

time java App

что позволяет не изменять код и время вашего приложения.


Это зависит от того, как вы запускаете код. Если это фрагмент кода, запускающий сервер, то вы собираетесь указать время запуска, которое неверно.
Арун Рамакришнан
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.