java - Fast MD5 Library 是不是比 Java 7 MD5 更快?

标签 java performance md5 benchmarking

所以我一直在寻找一种更快的方法来计算 MD5 校验和并遇到了 Fast MD5 library - 但是当我在我的机器上使用 Java 7 对其进行基准测试时,它比 Java 版本慢。

要么我在做一些愚蠢的事情(很可能),要么 Java 7 实现了更好的算法(也很可能)。这是我 super 简单的“基准”- 也许我今天没有喝足够的咖啡......

    MD5 digest = new MD5();
    System.out.println(MD5.initNativeLibrary(true));
    byte[] buff = IOUtils.readFully(new FileInputStream(new File("blahblah.bin")), 64000000, true);
    ByteBuffer buffer = ByteBuffer.wrap(buff);
    for (int j = 0; j < 100; j++) {
        start = System.currentTimeMillis();
        String md5Base64 = Utilities.getDigestBase64(buffer);
        end = System.currentTimeMillis();
        total = total + (end-start);
    }
    System.out.println("Took " + ((total)/100.00) + " ms. for " + buff.length+" bytes");
    total = 0;
    for (int i = 0; i < 100; i++) {
        start = System.currentTimeMillis();
        digest.Init();
        digest.Update(buff);
        digest.Final();
        end = System.currentTimeMillis();
        total = total + (end-start);
    }
    System.out.println("Took " + ((total)/100.00) + " ms. for " + buff.length+" bytes");

然后我得到:

Took 247.99 ms. for 64000000 bytes
Took 295.16 ms. for 64000000 bytes

根据评论,我一遍又一遍地运行 benchamrk,得到了最奇怪的结果。 FastMD5 计算保持不变,但 Java 7 版本变慢了。 ????

Took 246.54 ms. for 64000000 bytes
Took 294.69 ms. for 64000000 bytes
************************************
Took 540.55 ms. for 64000000 bytes
Took 292.69 ms. for 64000000 bytes
************************************
Took 537.07 ms. for 64000000 bytes
Took 292.12 ms. for 64000000 bytes

最佳答案

让我们先回答您问题的简单部分:

我认为当您再次运行代码时,您的 Java 7 执行时间大约翻倍,因为如果您只是将发布的代码放入 for 循环,您会忘记在执行之前将 total 重置为 0第 2、3、4、... Java 7 测试的运行(对于第一个,它可能从变量初始化中设置为 0)。

因此,通过简单地减去您未设置回 0 的偏移量来修复您的表格会得到:

Took 246.54 ms. for 64000000 bytes
Took 294.69 ms. for 64000000 bytes              <---.
************************************                |
Took 245.86 ms. for 64000000 bytes   (subtracting 294.69)
Took 292.69 ms. for 64000000 bytes              <---.
************************************                |
Took 244.38 ms. for 64000000 bytes   (subtracting 292.69)
Took 292.12 ms. for 64000000 bytes

现在,事情看起来非常一致,甚至显示了其他回复中提到的“JVM 预热”,而且它只产生了大约 1% 的差异。

现在,为什么 Java 7 的性能优于 FastMD5?

他们可能使用了一种更好的算法,该算法更适合 Java 编译器随后执行的优化。

例如,nio ByteBuffers 专门设计用于通过使用 DMA 等 native 事物来更快地访问内存。因此,MD5 的 Java 7 实现使用 ByteBuffer 而不是 byte[] 作为输入这一事实让我认为他们实际上正在利用这些功能(否则他们可能也只是采用了 byte[]。)

更进一步说,我们可能需要知道您的 Utilities 对象的确切功能,例如,然后比较 FastMD5 和 Java 实现的源代码。

但我要说:您的结果(给定 total=0 修复)对我来说非常有意义,您可能会享受这样一个事实,即您可以减少对外部库的依赖! ;)

顺便说一句:在 3.5GHz CPU 上,您看到的性能差异仅对应于每个处理数据字节大约 2-3 个 CPU 时钟周期(每个字节总共大约 15 个时钟周期)。因此,鉴于差异非常小,这很可能取决于所使用的确切平台和 JVM,两者中哪一个最终会更快。

添加

您的基准测试数字表明您可以使用这两个 MD5 实现处理大约 220-260MB/s,如果您查看 Google 搜索显示的其他声称的规范(例如“结果实现”下的 http://www.zorinaq.com/papers/md5-amd64.html),这听起来很合理。因此,与您收到的所有其他回复相反,我确实觉得我会相信您的数字。

如果您想更加确定,请改变 byte[] 的大小并查看由此产生的处理时间变化。如果一切正常,你会看到一个线性关系,你可以用这个函数来适应:

total/100.0 = m * buff.length + b           (your usual y = mx + b)

这里,m 是每个字节的处理时间,应该在 1/250MB/s = 4ns/byte 左右,b 是函数用来执行的设置时间初始化局部变量等,以及 System.currentTimeMillis(); 花费的时间。这个数字应该相当小(可能小于 1 毫秒)。

然后,要确定这两种算法中哪一种更适合您,您需要比较mb。如果您通常处理小型数据数组,b 可能会比 m 更重要地确定哪种算法更好,而对于大型数据集,具有较小 的算法>m 更好

关于java - Fast MD5 Library 是不是比 Java 7 MD5 更快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14637073/

相关文章:

ios - UIViewController 在 vi​​ewWillAppear 之后挂起

mysql - 子查询和连接之间的性能?

mysql - 创建哈希的 SQL 语法

linux - 如何在登录时比较 MD5 哈希值?

java - Java的正则表达式引擎是否在内部优化了字符类表达式?

java - 将参数传递给 java 的 List 类型的构造函数方法

mongodb - 如何在单机上使用 MongoDB 避免服务器故障时的数据丢失?

javascript - 如何在jquery中将密码转换成md5?

java - 使用 $$context 签署 JNLP 在 java 7.45 中不起作用

Java处理JSON