Как я могу измерить скорость кода, написанного на Java? (AI алгоритмы) - PullRequest
16 голосов
/ 08 марта 2010

Как измерить скорость кода, написанного на Java?

Я планирую разработать программное обеспечение, которое будет решать судоку, используя все доступные в настоящее время алгоритмы AI и ML, и сравнивать время с простым методом грубой силы. Мне нужно измерить время каждого алгоритма, я хотел бы спросить предложения о том, как лучше всего это сделать? Очень важно, что программа должна быть полезна на любом компьютере, независимо от мощности процессора / памяти.

Спасибо.

Ответы [ 5 ]

19 голосов
/ 08 марта 2010

Как подсказывают другие, 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%.

12 голосов
/ 08 марта 2010

Я обычно использую

System.currentTimeMillis()

для вычисления дельт времени:

long start = System.currentTimeMillis();
/* do your algorithm iteration */
long elapsed = System.currentTimeMillis() - start;

Помните, что в зависимости от используемой операционной системы точность функции может быть больше 1 миллисекунды(также десятая часть мсек), поэтому вам придется настроить его, чтобы он был полезен для вашего анализа.

РЕДАКТИРОВАТЬ: есть также альтернатива сделать то же самое с System.nanoTime(), но у вас нетгарантировать, что точность будет наносекунд.

5 голосов
/ 08 марта 2010

Это другой способ (с наносекундами)

long nanos = System.nanoTime();
// execute your stuff
long duration = System.nanoTime() - nanos;
int seconds = (int) (duration / 1000000000);
int milliseconds = (int) (duration / 1000000) % 1000;
int nanoseconds = (int) (duration % 1000000);
System.out.printf("%d seconds, %d milliseconds en %d nanoseconds\n", seconds, milliseconds, nanoseconds);

Нанос лишний, но приятный.

4 голосов
/ 11 марта 2010

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

4 голосов
/ 08 марта 2010

Если вас интересует точность измерений, вам следует измерять время процессора, а не «время настенных часов». Таким образом, вы не будете измерять время, которое ОС тратит на выполнение чего-то другого. Чтобы измерить это время, вы можете посмотреть процессорное время Java

...