我想创建性能测试,我使用AES加密数据,PKCPadding5 / 7取决于aix系统上的提供程序(IBM或BouncyCastle)。我的问题是为什么第一次枚举是如此缓慢和其他如此之快?
当我使用参数运行测试时:
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");
为什么?
答案 0 :(得分:2)
修订回答
第一次调用时加载和JIT编译代码需要花费时间 - 这就是为什么通常基准测试不包括第一次运行。 (事实上,许多JVM重新JIT越来越积极,因此性能会随着时间的推移而提高 - 所以好的基准测试会在计时之前多次运行代码。)
此外,认为加密提供商可能会做一些一次性设置并不是不合理的,特别是如果它正在尽力获得一些体面的熵。 (例如,它可能在内部使用SecureRandom
。)您可能希望分别对Cipher.getInstance
,Cipher.init
和Cypher.doFinal
方法调用进行计时,以确定哪个是慢速部分
最后,您还没有向我们展示所有代码(generateVectot
?),因此可能会有潜伏在那里的东西。
初步回答
显然randomString
是:
生成具有一定长度的随机字符串的简单函数,是的是使用SecureRandom,该实例只被打包一次
鉴于您正在寻找昂贵的东西(因为创建和使用SecureRandom
实例)并且只发生一次,这对我来说听起来像是一支冒烟的枪。
我建议您在System.currentTimeMillis
中添加时间(使用System.nanoTime
,而不是randomString
)来测试该假设。
我还强烈建议您不要使用使用平台默认编码的String.getBytes
的重载 - 而是始终明确指定编码。< / p>
答案 1 :(得分:0)
加密提供程序通常需要加载一些。这可以通过强制加载来看出。在这里,我尝试使用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
我的猜测是,您第一次使用提供商的任何内容时都会达到此加载时间。