Что не так с System.nanoTime?

У меня есть очень длинная строка с шаблоном </value> в самом конце, я пытаюсь проверить производительность некоторых вызовов функций, поэтому я сделал следующий тест, чтобы попытаться найти ответ... но я думаю, что могу использовать nanoTime неправильно? Потому что результат не имеет смысла, независимо от того, как я меняю порядок...

  long start, end;

  start = System.nanoTime();
  StringUtils.indexOf(s, "</value>");
  end = System.nanoTime();
  System.out.println(end - start);

  start = System.nanoTime();
  s.indexOf("</value>");      
  end = System.nanoTime();
  System.out.println(end - start);

  start = System.nanoTime();
  sb.indexOf("</value>");
  end = System.nanoTime();
  System.out.println(end - start);

Я получаю следующее:

163566    // StringUtils
395227    // String
30797     // StringBuilder

165619    // StringBuilder
359639    // String
32850     // StringUtils

Независимо от того, в каком порядке я их поменяю местами, числа всегда будут примерно одинаковыми... В чем тут дело?

Из часто задаваемых вопросов веб-сайта java.sun.com:

Использование System.nanoTime() между различными точками кода для измерения прошедшего времени всегда должно быть точным.

Также:

http://download.oracle.com/javase/1.5.0/docs/api/java/lang/System.html#nanoTime()


person codenamezero    schedule 22.11.2011    source источник


Ответы (3)


Разница между двумя прогонами составляет порядка микросекунд, и это ожидаемо. На вашей машине происходит много вещей, из-за которых среда выполнения никогда не бывает одинаковой между двумя запусками вашего приложения. Вот почему вы получаете эту разницу.

EDIT: Java API говорит:

Этот метод обеспечивает наносекундную точность, но не обязательно наносекундную точность.

person GETah    schedule 22.11.2011

Скорее всего, есть проблемы с инициализацией памяти или другие вещи, которые происходят при запуске JVM, которые искажают ваши цифры. Вы должны получить большую выборку, чтобы получить более точные цифры. Поэкспериментируйте с заказом, запустите его несколько раз и т. д.

person Andres Olarte    schedule 22.11.2011
comment
Да, я не думаю, что имеет смысл измерять время вызова одной простой функции. Вызов System.nanoTime, вероятно, занимает больше времени, чем работает сама строка. Может быть, @codenamezero вы могли бы попробовать запустить свой пример, но полностью удалив строковые функции; просто измеряя разницу во времени ничего 3 раза. - person toto2; 22.11.2011

Более чем вероятно, что методы, которые вы проверяете, используют какой-то общий код за кулисами. Но JIT выполнит свою работу только после примерно 10 000 вызовов. Следовательно, это может быть причиной того, что ваши первые два примера всегда кажутся медленнее.

Быстрое исправление: просто выполните 3 вызова метода перед первым измерением достаточно длинной строки.

person Ingo    schedule 22.11.2011
comment
все 3 из них используют String.indexOf() за кулисами - person soulcheck; 22.11.2011
comment
s.indexOf("</value>"); s.indexOf("</value>"); s.indexOf("</value>"); StringUtils.indexOf(s, "</value>"); StringUtils.indexOf(s, "</value>"); StringUtils.indexOf(s, "</value>"); sb.indexOf("</value>"); sb.indexOf("</value>"); sb.indexOf("</value>"); Черт возьми, не могу вставить ничего полезного, используя этот ответ, дерьмо... 30454 29086 27375 - person codenamezero; 22.11.2011