9

我发现在 java 中计算 sha256 很慢。例如,它比 python 慢。我写了两个简单的基准来计算 1GB 零的 sha256。在这两种情况下,结果都是相同且正确的,但是 python 时间是 5653 毫秒,而 java 时间是 8623 毫秒(慢了 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
4

4 回答 4

5

您是否尝试过以增量方式输入数据?您可以使用messageDigest.update()字节,然后使用messageDigest.digest()?

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

于 2011-10-21T08:33:20.930 回答
3

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

为了稍微清理一下,只需在代码本身的每个实际 MD5 计算之前和之后进行两次采样。

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

于 2011-10-21T08:35:53.137 回答
3

我对以下 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 第 8 代上运行的。Apache 和 Guava 很容易成为两个最快的实现。Apache Commons 在我运行的 9/10 中以微弱优势击败 Guava。我的测试代码可以在这里找到

请注意,运行此测试后,我开始怀疑是否可以通过利用 CPU 指令集(英特尔具有SHA 扩展)来更快。我不确定在没有 JNI 或 JNA 的情况下是否有 JVM 方法可以做到这一点。我在这里提出了另一个问题。

更新:我发现的另一个选项是Amazon Corretto Crypto Provider (ACCP)此处提供代码。

ACCP究竟是什么?

ACCP 实现了标准的 Java 加密体系结构 (JCA) 接口,并将默认的 Java 加密实现替换为 OpenSSL 项目中的 libcrypto 提供的实现。ACCP 允许您充分利用程序集级别和 CPU 级别的性能调整,以显着降低成本、减少延迟并提高跨多个服务和产品的吞吐量,如下面的示例所示。

于 2019-10-16T01:15:04.017 回答
0

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

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

于 2011-10-21T09:00:46.717 回答