本机加密哈希在Windows上的原生实现比.Net托管版本快多少?

12

为了对数据进行指纹识别并通过哈希标识数据,我提供了数据集的哈希值 - 这是快速哈希(如SHA1和MD5)的核心用例。

在.NET中,有选择使用某些哈希函数的本地或托管实现(无论如何,都是SHA变体)。我正在寻找MD5托管实现,似乎.NET Framework中没有这样的实现,但想知道包装后的本机CSP是否更快,以及是否应该放心地使用它而不会出现性能问题。回答.NET framework中为什么没有托管的MD5实现?的最佳答案表明,更快的性能可能是不存在托管变体的原因。

如果是这样,本机CSP能快多少呢?


MS实现的MD5很糟糕,至少对于短字符串而言是如此。通过p/invoking OpenSSL,我获得了约10倍的加速。 - CodesInChaos
我很高兴听到这个消息,因为我对测试OpenSSL实现非常感兴趣。 - codekaizen
小广告:如果您想要一个抗碰撞(不是MD5或SHA-1)的快速哈希函数来识别文件,那么您可以考虑使用Blake2。它就是为这种情况而设计的。但是,为了获得最大的性能,您需要一个本地库。 - CodesInChaos
好的,我会看一下。我使用Murmur3来跟踪一些内部数据的状态,但是Blake2看起来很有趣,特别是考虑到已发布的警报。 - codekaizen
1个回答

21

不幸的是,用于 MD5 的封装本地 CSP - MD5CryptoServiceProvider - 比纯托管实现要慢得多。有一种固执的观点认为本地代码比托管代码无疑更快:在许多情况下相反是真的。至少在头对头的测量中,这就是这样一个情况。

使用David Anson的翻译参考MD5实现,我构建了一个快速性能测试(源代码),旨在衡量两个实现之间的性能差异。虽然对于小数据数组,差异可以忽略不计,但在大约16kB左右时,本机实现开始显示潜在的显著延迟 - 大约几毫秒。这可能看起来并不多,但它比纯托管实现慢得多。随着哈希数据的大小增加,这种差异得以保持,并且在最大测试数据数组 - ~250MB时,CPU时间的差异约为8.5秒。考虑到这样的哈希通常用于指纹非常大的文件,即使与I/O通常更大的延迟相比,这种额外的延迟也会变得明显。
在这种情况下,延迟的来源并不十分清楚,因为没有进行纯本地测试(即不需要CSP包装和托管代码消耗的测试),但是考虑到在对数尺度上图形的几乎相同的形状,似乎托管和本地实现具有相同的固有性能,但本地代码性能“下移”,很可能是由于运行时本地和托管代码之间的互操作成本导致的。这种包装的本地CSP和纯托管实现之间的性能差异也已经被其他调查人员复制和记录
除了回答这个问题“本地实现有多快”之外,我希望这些证据可以促使更多的思考和调查,当涉及到本地与托管的问题时,打破长期以来对类似问题的刻板反应,即本地代码总是更快,因此更好。即使在这个性能敏感的大数据哈希领域,托管代码显然也非常快。

MD5 Hash Computation Time MD5 Hash Computation Time (Logarithmic)


“shifted” down 但在对数空间中,这相当于恒定因子的速度差异。因此,这可能是一个糟糕的本地实现。如果正确执行,本地应该在大数据上击败受管理的可测量性。 - usr
1
是的,那就是我所说的重点:“似乎托管代码和本机代码实现具有相同的内在性能”。但为什么本机代码会更快?除非你专门针对CLR jit不支持的硬件指令/寄存器,否则如果你分析jit输出并避免GC收集暂停,你将获得大约相同的性能。托管代码之所以不仅因为神奇原因而变慢,还有一些特定的东西会使它变慢,这可以避免敏感性能代码。 - codekaizen
2
我不同意托管代码和本地代码具有相同的内在性能,数据证明了这一点。数据反对跨平台调用在高数据量情况下会产生额外开销,因为跨平台调用的频率应该接近于零。 .NET JIT总体上表现相当糟糕。一个好的C编译器可以轻易胜过它。我详细研究了托管代码生成,它在许多方面都令人失望。例如,最近托管JIT才刚刚增加了对旋转指令的支持(但尚未发布)。 - usr
是的,旧版Jitter相当差劲。RyuJit已经更好了,并且开放源代码应该会有很大帮助(希望如此)。而且,是的,如果我们在本地生成的代码优化上付出一些努力,很容易做得更好。但我的观点是这不是神奇的。这并不意味着只因为代码是本地的就总是更快更好,这是我与其他开发人员交谈时发现的信仰。两者都可以很快,速度需要工作。是的,托管代码起始性能劣势,而Jitter限制了它,但最终可以使其变快。 - codekaizen
1
我在大约50个测试中详细比较了旧的JIT和RyuJIT,并比较了代码。除了极少数情况外,RyuJIT在各方面都比较差。循环中的范围检查是最大的改进。当然,JIT可以做得一样好甚至更好。Hotspot JVM非常出色。.NET JIT很差,这似乎是设计上的问题... :( - usr
我同意,Hotspot真是太棒了。我仍然对RyuJIT抱有希望。 - codekaizen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接