Среднее время, прошедшее с Java System.nanoTime, становится все меньше

Это не первый раз, когда у меня возникают проблемы с часами на языке программирования. В основном я измеряю, насколько быстро функция работает, вызывая ее в цикле while. Проблема в том, что по какой-то причине прошедшее время становится короче, чем дольше выполняется цикл while. Кто-нибудь может объяснить? Код ниже.

DescriptiveStatistics stats = new DescriptiveStatistics();
while(true) {
    long startTime = System.nanoTime();
    executeSaxonXsltTransformation();
    long stopTime = System.nanoTime();
    long elapsedTime = stopTime-startTime;
    stats.addValue((double)elapsedTime);
    System.out.println(stats.getN()+" - "+elapsedTime+ " - "+stats.getMean());
}

Таким образом, после примерно 1000 запусков затраченное время составляет от 750 до 850 тысяч. Но после примерно 100000 запусков затраченное время падает с 580k до 750k. Непрерывное уменьшение лучше всего заметить, наблюдая за средним значением (stats.getMeans ()), которое после 108 тыс. Циклов имеет в среднем ~ 632 тыс. Циклов по сравнению с 3 тыс. Циклов со средним значением ~ 1 миллион. Переход на currentTimeMillis вместо nanoTime ничего не меняет.


person Thirlan    schedule 15.03.2012    source источник


Ответы (2)


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

Если вы пытаетесь выполнить тест, вы должны «разогреть» тест, запустив метод в течение нескольких секунд без учета времени, и только затем приступить к измерению времени. В качестве альтернативы вы можете использовать библиотеку, которая знает, как проводить согласованный бенчмаркинг в Java - разогрев JIT, получение точных измерений вне зависимости от того, занимает ли ваш метод наносекунды или секунды - например, Caliper.

person Louis Wasserman    schedule 15.03.2012
comment
Спасибо, теперь это имеет смысл. У меня было ощущение, что что-то подобное происходит. - person Thirlan; 15.03.2012
comment
Знает ли Caliper, как проводить последовательные бенчмаркинг в наши дни? В последний раз, когда я смотрел на него, результат PrintCompilation не был обнадеживающим, мягко говоря. - person kittylyst; 16.03.2012
comment
Штангенциркуль очень хорош в микробенчмаркинге. Я признаю, что не знаю, как это работает на макро-тестах, но для измерения небольших, жестких методов это превосходно. - person Louis Wasserman; 16.03.2012

Проблема в том, что по какой-то причине прошедшее время становится короче, чем дольше выполняется цикл while. Кто-нибудь может объяснить?

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

person Jon Skeet    schedule 15.03.2012
comment
Еще до того, как я нажал на этот вопрос, я сказал себе: держу пари, что OP увидит скачок на 10 тыс. Итераций. Это порог по умолчанию для компиляции в серверном режиме. См. Также эту страницу о динамической компиляции. - person yshavit; 15.03.2012