2013-09-27 2 views
55

Сегодня я сделал немного быстрый Benchmark для тестирования производительности скорости System.nanoTime() и System.currentTimeMillis():Почему System.nanoTime() работает медленнее (по производительности), чем System.currentTimeMillis()?

long startTime = System.nanoTime(); 

for(int i = 0; i < 1000000; i++) { 
    long test = System.nanoTime(); 
} 

long endTime = System.nanoTime(); 

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

Это результаты:

System.currentTimeMillis(): average of 12.7836022/function call 
System.nanoTime():   average of 34.6395674/function call 

Почему различия в скорости бега настолько большой?

Benchmark система:

Java 1.7.0_25 
Windows 8 64-bit 
CPU: AMD FX-6100 
+0

Возможный дубликат [Почему System.nanoTime() и System.currentTimeMillis() так быстро расходятся?] (Http://stackoverflow.com/questions/5839152/why-do-system-nanotime-and-system -currenttimemillis-drift-apart-so-rapid) – chrylis

+0

Это сообщение может ответить на ваш вопрос: http://stackoverflow.com/a/5839267/658907 – matts

+0

'nanoTime' точнее, чем' currentTimeMillis', это может быть причиной. – Thomas

ответ

61

От this Oracle blog:

System.currentTimeMillis() осуществляется с использованием метода GetSystemTimeAsFileTime, который по существу только считывает низкое разрешение времени в день значение, для Windows поддерживает. Чтение этой глобальной переменной, естественно, очень быстро - около 6 циклов в соответствии с сообщила информацию.

System.nanoTime() осуществляется с помощью QueryPerformanceCounter/ QueryPerformanceFrequency API (если таковая имеется, иначе она возвращает currentTimeMillis*10^6). QueryPerformanceCounter(QPC) осуществляется по-разному в зависимости от оборудования он работает. Как правило, она будет использовать либо программируемый интервал таймера (PIT) или мощность ACPI таймер управления (PMT) или тайм-счетчик уровня CPU (TSC). Доступ к PIT/PMT требует выполнения инструкций порта медленного ввода-вывода и, как результат, время выполнения для QPC находится в порядке микросекунд. Напротив, считывание TSC осуществляется по порядку 100 тактов (чтобы прочитать TSC от микросхемы и преобразовать его в значение времени на основе рабочей частоты).

Возможно, это ответ на вопрос. Эти два метода используют различное количество тактовых циклов, что приводит к медленной скорости более поздней.

Далее в этом блоге в разделе Вывод:

Если вы заинтересованы в измерении/расчета затраченного времени, то всегда используйте System.nanoTime(). В большинстве систем это даст разрешение порядка микросекунд. Имейте в виду, однако, этот вызов также может принимать микросекунды для выполнения на некоторых платформах.

+10

Хороший ответ. Также этот сайт: http://stas-blogspot.blogspot.nl/2012/02/what-is-behind-systemnanotime.html Кто-то сделал небольшое исследование, а также показывает исходный код System.nanoTime для разных ОС. – MystyxMac

23

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

3

Это может быть только в Windows. См. this answer на аналогичный вопрос.

В основном, System.currentTimeMillis() просто считывает глобальную переменную, поддерживаемую Windows (что является низкой степенью детализации), тогда как System.nanoTime() фактически должен выполнять операции ввода-вывода.

0

Вы измеряете это на Windows, не так ли. Я прошел это упражнение в 2008 году. NanoTime IS медленнее в Windows, чем currentTimeMillis. Насколько я помню, на Linux нанотим быстрее, чем currentTimeMillis, и, безусловно, быстрее, чем в Windows.

Важно отметить, что если вы пытаетесь измерить совокупность нескольких операций в миллисекундах, вы должны использовать nanotime, как если бы операция закончилась менее чем на 1 000 секунд секунды вашего кода, сравнивая currentTimeMillis, операция как мгновенная, так что 1000 из них все равно будут мгновенными. Что вы можете сделать, это использовать nanotime затем округляется до ближайшей миллисекунды, поэтому, если операция была 8000 наносекунд будет считаться 1 миллисекунды, а не 0.

0

Что вы можете сделать, это использовать nanotime то округление до ближайшего миллисекунды, поэтому, если операция была 8000 наносекунд будет считаться 1 миллисекунды, а не 0.

Арифметика примечание:

8000 наносекунд 8 микросекунд составляет 0,008 миллисекунды. Округление займет примерно до 0 миллисекунд.

Смежные вопросы