Как подсказывают другие, System.currentTimeMillis()
довольно хорошо, но обратите внимание на следующие предостережения:
System.currentTimeMillis()
измеряет прошедшее физическое время («время настенных часов»), а не время ЦП. Если на компьютере запущены другие приложения, ваш код будет загружен меньше, а его скорость снизится. Таким образом, скамейка только на бездействующих системах.
- Аналогичным образом, многопоточное приложение в многоядерной системе может получить дополнительный скрытый процессор. Мера истекшего времени не отражает всей сложности многопоточных приложений.
- Java нужно немного "прогреться". Виртуальная машина сначала интерпретирует код (который работает медленно), и, если данный метод используется слишком много раз, компилятор JIT преобразует метод в собственный код. Только в этот момент метод достигнет максимальной скорости. Я рекомендую вам выполнить несколько «пустых циклов» перед вызовом
System.currentTimeMillis()
.
- Точность
System.currentTimeMillis()
редко составляет 1 мс. Во многих системах точность не лучше, чем 10 мс или даже больше. Кроме того, JVM иногда запускает GC, вызывая заметные паузы. Я предлагаю вам организовать вашу меру в цикле и настаивать на том, чтобы она длилась не менее нескольких секунд.
В результате получается следующий код:
for (int i = 0; i < 10; i ++) {
runMethod();
}
int count = 10;
for (;;) {
long begin = System.currentTimeMillis();
for (int i = 0; i < count; i ++)
runMethod();
long end = System.currentTimeMillis();
if ((end - begin) < 10000) {
count *= 2;
continue;
}
reportElapsedTime((double)(end - begin) / count);
}
Как видите, есть первые десять "пустых" трасс. Затем программа запускает метод в цикле столько раз, сколько необходимо, чтобы цикл занял не менее десяти секунд. Десять секунд должно быть достаточно для сглаживания прогонов ГХ и других неточностей системы. Когда я тестирую реализации хэш-функций, я использую две секунды, и хотя сама функция не вызывает никакого выделения памяти, я все равно получаю вариации до 3%.