0

Измерение накладных расходов на время в Java

9

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

System.currentTimeMillis();
System.nanoTime();

Оба метода реализованы native. Прежде чем углубляться в какой-либо код на C, есть ли у кого-то информация о том, есть ли значительная задержка при вызове одного из них? Я имею в виду, если мне неважна дополнительная точность, какой из них можно ожидать, что будет менее затратным по времени CPU?

Примечание: Я использую стандартный JDK Java 1.6, но вопрос может быть актуален для любой JRE...

5 ответ(ов)

0

На теоретическом уровне, для виртуальной машины (VM), которая использует родные потоки и работает на современном прерываемом операционной системе, метод currentTimeMillis может быть реализован так, чтобы выполняться только один раз за тайм-срез. Предположительно, реализации метода nanoTime не будут жертвовать точностью.

Если у вас есть дополнительные вопросы по поводу реализации или необходимости в более детальных примерах, не стесняйтесь задавать их!

0

Не думаю, что вам стоит беспокоиться о накладных расходах на оба метода. Они настолько малы, что их едва ли можно измерить. Вот быстрый микро-бенчмарк для обоих:

for (int j = 0; j < 5; j++) {
    long time = System.nanoTime();
    for (int i = 0; i < 1000000; i++) {
        long x = System.currentTimeMillis();
    }
    System.out.println((System.nanoTime() - time) + "нс на миллион");

    time = System.nanoTime();
    for (int i = 0; i < 1000000; i++) {
        long x = System.nanoTime();
    }
    System.out.println((System.nanoTime() - time) + "нс на миллион");

    System.out.println();
}

И последние результаты:

14297079нс на миллион
29206842нс на миллион

Действительно, System.currentTimeMillis() кажется в два раза быстрее, чем System.nanoTime(). Однако 29нс — это гораздо меньше, чем что-либо другое, что вы будете измерять. Я бы рекомендовал использовать System.nanoTime() для большей точности и достоверности, так как он не связан с часами.

0

Вы всегда должны использовать System.nanoTime() для измерения времени выполнения. Дело не только в наносекундной точности; System.currentTimeMillis() возвращает "реальное время", в то время как System.nanoTime() предназначен для замеров времени и не имеет тех "проблем с реальным временем", которые есть у другого метода. Из документации Javadoc к System.nanoTime():

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

0

System.currentTimeMillis() обычно работает очень быстро (по моим данным, около 5-6 циклов ЦП, но не помню, где это читал), однако его разрешение может различаться на разных платформах.

Если вам нужна высокая точность, используйте nanoTime(). Если вас беспокоит накладные расходы, лучше выбрать currentTimeMillis().

0

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

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь