为什么第一次加密数据的枚举需要很长时间

时间:2014-04-01 13:54:19

标签: java performance encryption

我想创建性能测试,我使用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");

为什么?

2 个答案:

答案 0 :(得分:2)

修订回答

第一次调用时加载和JIT编译代码需要花费时间 - 这就是为什么通常基准测试包括第一次运行。 (事实上​​,许多JVM重新JIT越来越积极,因此性能会随着时间的推移而提高 - 所以好的基准测试会在计时之前多次运行代码。)

此外,认为加密提供商可能会做一些一次性设置并不是不合理的,特别是如果它正在尽力获得一些体面的熵。 (例如,它可能在内部使用SecureRandom。)您可能希望分别对Cipher.getInstanceCipher.initCypher.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

我的猜测是,您第一次使用提供商的任何内容时都会达到此加载时间。