Как я могу измерить время с точностью до микросекунды в Java? - PullRequest
21 голосов
/ 02 февраля 2009

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

По сути, у меня есть этот код, который, например, выполняет от 1 до 10 миллионов вставок в связанный список Java. Проблема в том, что я не могу измерить правильную точность; иногда для вставки всего в меньший список требуется меньше времени.

Вот пример:

class test
{
    public static void main(String args[])
    {
        for(int k=1000000; k<=10000000; k+=1000000)
        {
            System.out.println(k);
            LinkedList<Integer> aux = new LinkedList<Integer>();
            //need something here to see the start time
            for(int i=0; i<k; i++)
                aux.addFirst(10000);
            //need something here to see the end time
            //print here the difference between both times
        }
    }
}

Я делал это много раз - внешний цикл делал это 20 раз для каждого k - но результат не очень хороший. Иногда для создания 10 миллионов вставок требуется меньше времени, чем для 1 миллиона, поскольку я не получаю правильное измеренное время с тем, что я использую сейчас (System.nanoTime ())

Редактировать 2: Да, я использую Sun JVM.

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

Редактировать 4: Моя ошибка, кажется, System.nanoTime () работает. Уф.

Ответы [ 12 ]

30 голосов
/ 02 февраля 2009

Я предполагаю, что, поскольку System.nanoTime() использует "самый точный из доступных системных таймеров", который, очевидно, имеет в вашей системе только миллисекундную точность, вы не можете получить ничего лучше.

25 голосов
/ 02 февраля 2009

Мне не совсем ясно, что именно вы тестируете, но в целом любой тест, который занимает такой короткий промежуток времени для запуска, эта точность ниже 50 мс имеет значение быть очень склонным к другим нарушениям.

Обычно я стараюсь, чтобы тесты запускались не менее 10 секунд. Фреймворк, который я сейчас пишу, будет угадывать, сколько итераций нужно выполнить, так что это займет 30 секунд. Это означает, что вы не получите радикально других результатов только потому, что какой-то другой процесс украл ЦП на несколько миллисекунд.

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

4 голосов
/ 02 февраля 2009

System.nanoTime() использует счетчик в ЦП и обычно с точностью до 1 микросекунды в Windows XP и Linux.

Примечание: Windows XP часто менее точна на компьютерах с несколькими процессорами, поскольку она не компенсирует разные процессоры, имеющие разные счетчики. Linux делает. Примечание 2: он будет дрейфовать относительно System.currentTimeMillis (), так как он основан на точности часов вашего процессора (которые не должны быть такими точными в течение определенного периода времени), а не на ваших часах для получения времени. (который дрейфует меньше в день, но имеет меньшую детализацию)

В своем тесте вы в основном тестируете скорость, с которой вы можете создавать новые объекты. Неудивительно, что ваши результаты будут сильно отличаться в зависимости от настроек ГХ и того, как недавно был выполнен ГХ.

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

-verbosegc -XX:NewSize=128m -mx256m
3 голосов
/ 19 февраля 2017

Использование java.time

FYI, Java 9 и более поздние версии имеют новую реализацию Clock, которая может фиксировать текущий момент с разрешением до наносекунд.

Класс Instant представляет момент на временной шкале в UTC с разрешением наносекунд (до девяти (9) цифр десятичного знака доля).

Позвоните Instant.now, чтобы зафиксировать текущий момент.

  • В Java 9 и более поздних версиях вы получаете разрешение до наносекунд на данный момент.
  • В Java 8 текущий момент фиксируется только с разрешением миллисекунд (вы действительно можете хранить значения с наносекундами, но только захватывать текущий момент в миллисекундах).

    Мгновенное мгновение = Instant.now ();

Представляет промежуток времени, не привязанный к временной шкале с классом Duration. Содержит количество времени в секундах и наносекундах.

Duration d = Duration.between( instantThen , Instant.now() );

Для ясности, разрешение микросекунд , заданное в Вопросе, находится между гранулярностями миллисекунд и наносекунд. Число знаков после запятой: миллис равен 3 (0,123), микро - 6 (0,123456), нанос - 9 (0,123456789).

* * Тысяча сорок-девять * 1050 Caveat *

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

Бенчмаркинг при такой тонкой детализации чреват проблемами и вообще не рекомендуется вообще.

И остерегайтесь преждевременной оптимизации .

Существует предложение о добавлении средства микро-бенчмаркинга для платформы Java в JEP 230: Microbenchmark Suite . На основе Java Microbenchmark Harness (JMH) .


О java.time

Фреймворк java.time встроен в Java 8 и более поздние версии. Эти классы вытесняют проблемные старые устаревшие классы даты и времени, такие как java.util.Date, Calendar, & SimpleDateFormat.

Проект Joda-Time , теперь в режиме обслуживания , рекомендует перейти на классы java.time .

Чтобы узнать больше, см. Oracle Tutorial . И поиск переполнения стека для многих примеров и объяснений. Спецификация JSR 310 .

Где получить классы java.time?

  • Java SE 8 и SE 9 и более поздние
    • Встроенный.
    • Часть стандартного Java API со встроенной реализацией.
    • Java 9 добавляет некоторые незначительные функции и исправления.
  • Java SE 6 и SE 7
    • Большая часть функциональности java.time перенесена в Java 6 & 7 в ThreeTen-Backport .
  • Android

Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time. Здесь вы можете найти несколько полезных классов, таких как Interval, YearWeek, YearQuarter и more .

3 голосов
/ 03 февраля 2009

Если вы хотите надежный результат, используйте профилировщик. Я предлагаю VisualVM , который прост в установке и поставляется в комплекте с JDK, начиная с версии 1.6.0_07.

Это простой в использовании визуальный инструмент, который объединяет несколько инструментов командной строки JDK и легкие возможности профилирования.

3 голосов
/ 02 февраля 2009

Вы должны повторить тесты тысячи раз. Происходит много вещей, которые будут влиять на ваши измерения, такие как сборка мусора, ввод-вывод, подкачка / выгрузка, размер потоков готовой очереди и т. Д.

3 голосов
/ 02 февраля 2009

Странно. System.nanoTime () должен работать. Вы используете Sun JVM?

Можете ли вы просто повторить свою операцию 1000 раз и поделить время на 1000, чтобы узнать, что вам нужно знать?

1 голос
/ 19 августа 2011

Да, точность и точность System.nanoTime обычно намного лучше, чем System.currentTimeMillis, но без гарантии: в худшем случае она может стать такой же плохой.

ThreadMXBean.getCurrentThreadCpuTime имеет тенденцию давать меньшие времена, но его разрешение неясно, и у него есть дополнительные недостатки (вы действительно хотите время процессора?

Измерение времени всеми тремя методами также имеет определенную стоимость, т. Е. Требует само время, которое может исказить измерения. Затраты сильно зависят от платформы, но часто стоят (System.currentTimeMillis) << cost (System.nanoTime) << cost (ThreadMXBean.getCurrentThreadCpuTime). </p>

О микротестном тестировании в целом см.

1 голос
/ 02 февраля 2009

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

Существует также более старая запись .

0 голосов
/ 13 июля 2016

Для нашего последнего профилирования я обнаружил, что ThreadMXBean.getCurrentThreadCpuTime() и опция -XX:+UseLinuxPosixThreadCPUClocks сделали то, что нам нужно.

Подробнее см. http://bugs.java.com/view_bug.do?bug_id=6888526

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...