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

Hri*_*tov 7 java optimization sha sha256

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

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

基准:

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));
  }

}
Run Code Online (Sandbox Code Playgroud)

蟒蛇:

#!/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)
Run Code Online (Sandbox Code Playgroud)

结果:

~> java BenchmarkSha256
49bc20df15e412a64472421e13fe86ff1c5165e18b2afccf160d4dc19fe68a14
8623 ms

~> python BenchmarkSha256.py 
49bc20df15e412a64472421e13fe86ff1c5165e18b2afccf160d4dc19fe68a14
5653 ms
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

Sco*_*ott 6

我对以下 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
Run Code Online (Sandbox Code Playgroud)

这是在 Intel i5 第 8 代上运行的。Apache 和 Guava 很容易成为两个最快的实现。在我的跑步中有 9/10,Apache Commons 以微弱优势击败了 Guava。我的测试代码可以在这里找到。

请注意,运行此测试后,我开始想知道是否可以通过利用 CPU 指令集(Intel 有SHA 扩展)来加快速度。我不确定是否有一种 JVM 方法可以在没有 JNI 或 JNA 的情况下执行此操作。我在这里创建了另一个问题。

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

ACCP到底是什么?

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


Jef*_*ter 5

您是否尝试过增量输入数据?您可以使用messageDigest.update()字节,然后使用messageDigest.digest()?获取最终摘要。

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