java - 为什么第一次枚举加密数据需要这么长时间

标签 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");

为什么?

最佳答案

修改后的答案

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

此外,认为加密货币提供商很可能会进行一些一次性设置并不是没有道理的,特别是如果它正在尽最大努力获得一些像样的熵。 (例如,它可能在内部使用 SecureRandom。)您可能需要对 Cipher.getInstanceCipher.init 进行计时。 Cypher.doFinal方法单独调用,以确定哪个部分是慢的。

最后,您还没有向我们展示所有代码(generateVectot?),因此可能存在潜伏的东西。

初始答案

显然randomString是:

simple function which generate random string with certain length and yes is use SecureRandom which instance is crateted just once

鉴于您正在寻找昂贵的东西(如创建和使用 SecureRandom 实例)并且仅发生一次,这对我来说听起来像是确凿无疑的证据。

我建议您在 randomString 中添加计时(使用 System.nanoTime,而不是 System.currentTimeMillis)来测试该假设。

<小时/>

我还强烈建议您不要使用使用平台默认编码的String.getBytes重载 - 相反,始终显式指定编码。

关于java - 为什么第一次枚举加密数据需要这么长时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22788031/

相关文章:

java - 是否可以在调用方服务器上添加 CORS header ?

java - Hibernate:持久化树状结构

Java 正则表达式 电话号码

java - 我怎样才能使这段代码更有效地找到一对总和?

Java DESede 加密,OpenSSL 等效

java - 将标题栏添加到 JFrame (Linux)

c# - 枚举性能

python - 如何避免使用日期时间列的 pandas mean() 性能不佳

c# - 对称密码算法之间的区别

git - 我可以为 Travis YAML 配置命令创建 ALIAS 吗? ... "travis encrypt GITHUB_TOKEN=****** --add"?