Измерьте время выполнения - PullRequest
2 голосов
/ 24 января 2011

Я хочу измерить время, необходимое для генерации ключа DES, и хочу вычислить его несколько раз, чтобы найти среднее значение.

for (int x = 0; x < 10; x++)
{
     long startTime = System.currentTimeMillis();

     SecretKey key = KeyGenerator.getInstance("DES").generateKey();         

     long stopTime = System.currentTimeMillis();
     long elapsedTime = stopTime - startTime;
     System.out.println("Total Time Taken : " + elapsedTime);
}

но результат получается как

Total Time Taken : 251
Total Time Taken : 0
Total Time Taken : 0
Total Time Taken : 0
Total Time Taken : 0
Total Time Taken : 0
Total Time Taken : 0
Total Time Taken : 0
Total Time Taken : 0
Total Time Taken : 0

Я попытался избавиться от ключевого объекта, установив его в null, а затем вызвав System.gc ();но это не сработало.

Любое предложение или идея по преодолению этой проблемы.

Ответы [ 7 ]

4 голосов
/ 24 января 2011

Подтвердите ваши счета. Мощность разрешения currentTimeMillis () ограничена возможностями оборудования и ОС. В частности, он не способен на самом деле разрешить до абсолютного точного мс. Я обнаружил, что это не точно в диапазоне 300 мс.

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

2 голосов
/ 24 января 2011

Микро стендовая маркировка сложна. Я предлагаю вам использовать для этого открытый проект Google Caliper .

Как написать правильный микро-тест на Java?

2 голосов
/ 24 января 2011

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

1 голос
/ 24 января 2011

Может быть трудно измерить действительно маленькое значение - например, попытаться измерить ширину цента с помощью линейки. Лучше измерить 10 или 20 из них в стеке, а затем разделить результат измерения на количество в стеке.

int iterations = 1000;

long startTime = System.currentTimeMillis();
for (int x = 0; x < iterations; x++) {
     SecretKey key = KeyGenerator.getInstance("DES").generateKey();         
}
long stopTime = System.currentTimeMillis();

long elapsedTime = stopTime - startTime;
double average = elapsedTime/((double) iterations);
System.out.println("Total Time Taken : " + average + " ms");
1 голос
/ 24 января 2011

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

Вы получите более точное время, если будете использовать System.nanoTime() вместо System.currentTimeMillis().Результаты будут выглядеть так:

Total Time Taken : 687562592
Total Time Taken : 51328
Total Time Taken : 33838
Total Time Taken : 25474
Total Time Taken : 22432
Total Time Taken : 29656
Total Time Taken : 23192
Total Time Taken : 28516
Total Time Taken : 22812
Total Time Taken : 21672
1 голос
/ 24 января 2011

251 мс в начальном вызове в основном представляют JVM, которая ищет правильного поставщика для алгоритма "DES" и инициализирует связанное с ним состояние.

Ключи DES - это просто случайные 64-битные значения (ну вообще 56, но это уже другая история).Я ожидаю, что это займет менее миллисекунды.

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

0 голосов
/ 24 января 2011

Это может быть из-за оптимизации времени выполнения JVM. Таким образом, при первом запуске он выполняет профилирование, а при последующих вызовах метод выполняется намного быстрее.

Также это может быть связано с методом - первый вызов может выполнить некоторую работу по инициализации, такую ​​как загрузка классов, создание объектов и т. Д.

Обычно, при выполнении бенчмаркинга кода Java рекомендуется отменить несколько первых вызовов.

РЕДАКТИРОВАТЬ: И в вашем случае, если вы нигде не используете этот экземпляр SecretKey, JVM может решить, что он вообще не нужен, и этот код даже не вызывается в процессе.

...