Я хочу создать тест производительности, где я шифрую данные, используя AES с PKCPadding5/7, зависит от поставщика (IBM или BouncyCastle) в системе aix. Мой вопрос в том, почему первое перечисление происходит так медленно и так быстро?
Когда я запускаю тест с параметрами:
Padding: AES/CBC/PKCS7Padding
Provider: BC version 1.47
Number of iteration: 1000
результаты:
Time: 392080057 ns
Time: 174662 ns
Time: 160906 ns
Time: 169938 ns
Time: 154344 ns
Time: 155125 ns
Time: 157344 ns
Time: 157203 ns
Time: 157611 ns
Time: 158123 ns
параметры
Padding: AES/CBC/PKCS5Padding
Provider: IBMJCE version 1.7
Number of iteration: 1000
результаты:
Time: 13410344 ns
Time: 185007 ns
Time: 182562 ns
Time: 170687 ns
Time: 203156 ns
Time: 189980 ns
Time: 182608 ns
Time: 174670 ns
Time: 176842 ns
Time: 174463 ns
Код:
for (int j = 0; j < pocetIteraci; j++) {
String text = randomString(46);
long time = System.currentTimeMillis();
sifruj(padding, provider, generateVectot(),text);
time = System.currentTimeMillis() - time;
System.out.println("Time: " + time + " ms");
}
public static byte[] sifruj(String padding, Provider provider, IvParameterSpec finalniInicializacniVektor,String text)
throws Exception {
return zpracuj(padding, provider, text.getBytes("UTF-8"), finalniInicializacniVektor, Cipher.ENCRYPT_MODE);
}
public static byte[] zpracuj(String padding, Provider provider, byte[] data,
IvParameterSpec finalniInicializacniVektor, int mode) throws Exception {
final SecretKeySpec klicSpec = new SecretKeySpec(klic, ALGORITHM_AES);
final Cipher sifra = Cipher.getInstance(padding, provider);
sifra.init(mode, klicSpec, finalniInicializacniVektor);
return sifra.doFinal(data);
}
ОБНОВЛЕНО:
Наиболее разные (как я и ожидал) - это создание первого экземпляра шифрования:
long timeTemp = System.nanoTime();
final Cipher sifra = Cipher.getInstance(padding, provider);
timeTemp = System.nanoTime() - timeTemp;
System.out.println("XXXXXXXXXXXXXXXXX " + timeTemp + " ns");
Зачем?
Пересмотренный ответ
Время, затрачиваемое на загрузку и JIT-компиляцию кода при первом вызове, - то почему обычно эталонные тесты не включают первый запуск. (На самом деле, многие JVM снова и более активно работают, поэтому производительность улучшается с течением времени, поэтому хорошие тесты запускаются много раз, прежде чем синхронизировать их.)
Кроме того, неразумно думать, что поставщик криптографии может сделать некоторую разовую настройку, особенно если он изо всех сил пытается получить приличную энтропию. (Например, он может использовать SecureRandom
.) Возможно, вы захотите, чтобы Cipher.getInstance
, Cipher.init
и Cypher.doFinal
отдельно, чтобы определить, какая из них является медленной.
Наконец, вы не показали нам весь код (generateVectot
?), Так что там могут быть вещи, скрывающиеся там.
Первоначальный ответ
Очевидно, randomString
:
простая функция, генерирующая случайную строку с определенной длиной и да - это использование SecureRandom, экземпляр которого кратёт только один раз
Учитывая, что вы ищете что-то дорогое (как создание и использование экземпляра SecureRandom
), и это происходит только один раз, это звучит как курящий пистолет для меня.
Я предлагаю вам добавить время (используя System.nanoTime
, а не System.currentTimeMillis
) в randomString
чтобы проверить эту гипотезу.
Я также настоятельно рекомендую вам не использовать перегрузку String.getBytes
которая использует стандартную кодировку платформы - вместо этого всегда указывайте кодировку явно.
Поставщикам криптографии обычно требуется немного загрузки. Это можно увидеть, заставив его загрузить. Здесь я пытаюсь связаться с поставщиком IBM JCE):
public class Test {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
Security.addProvider(new com.ibm.crypto.provider.IBMJCE());
long endTime = System.currentTimeMillis();
System.out.println("Time to load: " + (endTime - startTime));
}
}
дает:
Time to load: 72
Я предполагаю, что вы нажмете это время загрузки в первый раз, когда используете что-либо у поставщика.
randomString
? Использует ли онSecureRandom
случайно?