如何在java中更快地计算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));
}
}
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
I have found out that calculating sha256 in java is slow. For example, it is slower than python. I wrote two simple benchmarks that calculate sha256 of 1GB of zeroes. In both cases the result is the same and correct, but the python time is 5653ms and the java time is 8623ms(53% slower). The result is similar every time and this is an important difference for me.
How to make the calculation in java faster?
Benchmarks:
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)
results:
~> java BenchmarkSha256
49bc20df15e412a64472421e13fe86ff1c5165e18b2afccf160d4dc19fe68a14
8623 ms
~> python BenchmarkSha256.py
49bc20df15e412a64472421e13fe86ff1c5165e18b2afccf160d4dc19fe68a14
5653 ms
versions of java and 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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我对以下 SHA-256 实现进行了测试:Java 内置、Groovy 内置、Apache Commons、Guava 和 Bouncy Castle。我的一次运行结果如下:
这是在 Intel i5 第 8 代上运行的。Apache 和 Guava 很容易成为两个最快的实现。在我的跑步中有 9/10,Apache Commons 以微弱优势击败了 Guava。我用于此测试的代码可在此处获取。
请注意,运行此测试后,我开始想知道是否可以通过利用 CPU 指令集来加快速度(Intel 有 SHA 扩展)。我不确定是否有一种 JVM 方法可以在没有 JNI 或 JNA 的情况下执行此操作。我在此处创建了另一个问题。
更新:我发现的另一个选项是 Amazon Corretto 加密货币提供商 (ACCP)。代码可在此处获取。
I ran a test on the following SHA-256 implementations: Java built-in, Groovy built-in, Apache Commons, Guava, and Bouncy Castle. My results on one run are here:
This was run on an Intel i5 8th Gen. Apache and Guava were easily to two fastest implementations. Apache Commons narrowly beat out Guava on 9/10 of my runs. My code for this test is available here.
Note that after running this test I started to wonder if you could go even faster by tapping into the CPU instruction set (Intel has SHA extensions). I'm not sure there is a JVM way to do this without JNI or JNA. I created another question here.
Update: Another option I found is the Amazon Corretto Crypto Provider (ACCP). Code available here.
您是否尝试过增量输入数据?您可以将
messageDigest.update()
与字节一起使用,然后使用messageDigest.digest()
获取最终摘要吗?在内存中分配 1GB 数组是一个相当大的操作。您可能会发现较小的增量更新最终会更快。
Have you tried feeding in the data incrementally? You can use
messageDigest.update()
with the bytes and then get the final digest withmessageDigest.digest()
?Allocating a 1GB array in memory is a fairly chunky operation. You may find that smaller incremental updates are faster in the end.
好吧,除非您这样做是为了比较两个命令行程序,否则这不是最好的测试。主要是,这些数字受到与每个程序相关的巨大开销差异的影响。 VM 启动时间会有所不同。内存分配速度会有所不同。
为了稍微清理一下这个问题,只需在代码本身的每次实际 MD5 计算之前和之后获取两个时间样本。
这实际上将衡量散列操作本身的性能。
Well, unless you are doing this to compare two command line programs, this is not the best test. Primarily, these numbers are being polluted by the vast differences in overhead associated with each program. VM start times will vary. Memory allocation speeds will vary.
To clean this up a bit, simply take two time samples before and after each actual MD5 calculation within the code itself.
This will actually measure performance of the hashing operation itself.
虽然您可能能够稍微提高 Java 工具的性能,但 Python 实现通常会更快,因为它可能委托给以明显更好的性能运行的组装库。
如果您的项目对 Java 没有任何其他重要依赖项,我建议使用 Python 实现。
While you might be able to improve the performance of the Java tool a bit, the Python implementation will usually be faster because it is likely delegating to assembled libraries which run with significantly better performance.
If your project does not have any other significant dependencies on Java, I'd recommend going with the Python implementation.