如何在java中更快地计算sha256?

时间:2011-10-21 08:25:15

标签: java optimization sha256 sha

我发现在java中计算sha256很慢。例如,它比python慢​​。我写了两个简单的基准测试来计算1GB零的sha256。在这两种情况下,结果都是相同且正确的,但python时间是5653ms,java时间是8623ms(慢53%)。结果每次都很相似,这对我来说是一个重要的区别。

如何更快地在java中进行计算?

基准:

爪哇:

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class BenchmarkSha256 {

  public static void main(String... args) throws NoSuchAlgorithmException {
    int size = 1024 * 1024;
    byte[] bytes = new byte[size];
    MessageDigest md = MessageDigest.getInstance("SHA-256");
    long startTime = System.nanoTime();
    for (int i = 0; i < 1024; i++)
      md.update(bytes, 0, size);
    long endTime = System.nanoTime();
    System.out.println(String.format("%1$064x", new java.math.BigInteger(1, md.digest())));
    System.out.println(String.format("%d ms", (endTime - startTime) / 1000000));
  }

}

的Python:

#!/usr/bin/env python

import hashlib
import time

size = 1024 * 1024
bytes = bytearray(size)
md = hashlib.sha256()
startTime = time.time()
for i in range(0, 1024):
  md.update(bytes)
endTime = time.time()
print "%s\n%d ms" % (md.hexdigest(), (endTime - startTime) * 1000)

结果:

~> java BenchmarkSha256
49bc20df15e412a64472421e13fe86ff1c5165e18b2afccf160d4dc19fe68a14
8623 ms

~> python BenchmarkSha256.py 
49bc20df15e412a64472421e13fe86ff1c5165e18b2afccf160d4dc19fe68a14
5653 ms

java和python的版本:

~> java -version
java version "1.6.0_26"
Java(TM) SE Runtime Environment (build 1.6.0_26-b03)
Java HotSpot(TM) 64-Bit Server VM (build 20.1-b02, mixed mode)

~> python --version
Python 2.7

6 个答案:

答案 0 :(得分:4)

您是否尝试过逐步输入数据?您可以将messageDigest.update()与字节一起使用,然后使用messageDigest.digest()获取最终摘要?

在内存中分配1GB阵列是一项相当庞大的操作。您可能会发现较小的增量更新最终会更快。

答案 1 :(得分:3)

好吧,除非你这样做比较两个命令行程序,否则这不是最好的测试。主要是,这些数字受到与每个程序相关的开销的巨大差异的污染。 VM启动时间会有所不同。内存分配速度会有所不同。

要稍微清理一下,只需在代码本身的每个实际MD5计算之前和之后取两个时间样本。

这实际上会测量散列操作本身的性能。

答案 2 :(得分:0)

我认为java本质上很慢。这个问题可能与您有关Java: Calculate SHA-256 hash of large file efficiently

答案 3 :(得分:0)

虽然您可能能够稍微提高Java工具的性能,但Python实现通常会更快,因为它可能会委托组装的库运行,性能会明显提高。

如果您的项目没有任何其他重要的Java依赖项,我建议您使用Python实现。

答案 4 :(得分:0)

我对以下SHA-256实现进行了测试:内置Java,内置Groovy,Apache Commons,Guava和Bouncy Castle。我的一次运行结果在这里:

>groovy hash_comp.groovy
Hashing 1000000 iterations of SHA-256
time java: 2688         372023.8095238095 hashes/sec
time groovy: 1948       513347.0225872690 hashes/sec
time apache: 867        1153402.5374855825 hashes/sec
time guava: 953         1049317.9433368311 hashes/sec
time bouncy: 1890       529100.5291005291 hashes/sec

这是在Intel i5 8th Gen上运行的。Apache和Guava可以轻松实现两个最快的实现。在我跑步的9/10中,Apache Commons勉强击败了Guava。我可以通过here获得此测试的代码。

请注意,运行此测试后,我开始怀疑您是否可以通过使用CPU指令集(Intel具有SHA extensions)来更快地运行。我不确定没有JNI或JNA可以采用JVM的方式来做到这一点。我创建了另一个问题here

更新:我发现的另一个选项是Amazon Corretto Crypto Provider (ACCP)。可用的代码here

  

什么是ACCP?

     

ACCP实现标准的Java密码体系结构(JCA)接口,并用OpenSSL项目的libcrypto提供的默认Java密码实现替换。通过ACCP,您可以充分利用程序集级和CPU级的性能调整,从而显着降低成本,减少延迟,并跨多个服务和产品获得更高的吞吐量,如以下示例所示。

答案 5 :(得分:-4)

使用标准JRE无法做到这一点。外部库应该使用更快,可能是本机实现。