10

我正在寻找在 JavaScript 中实现的低冲突的快速哈希。它不需要是加密哈希。我基本上使用它来查看给定文件是否已经上传(或部分上传)到用户的帐户,以节省他们在大型(视频)文件上的一些上传时间。

我正在使用新的 HTML5 File API 读取文件的片段。然后我把它交给SparkMD5给我一个文件的哈希值。我喜欢 SparkMD5 允许我进行增量散列的事实,因此我不必在内存中读取整个内容。

总的来说,SparkMD5 可以满足我的需求,但对于大文件,我可能需要一段时间才能获得我的哈希值(300MB 文件大约需要 30 秒)。理想情况下,我想减少这种情况。我对哈希函数并不了解,所以我不想移植一些东西,理想情况下我正在寻找一个已经实现的库。

4

1 回答 1

8

更新(2021 年 8 月):我的基准测试早于 WebAssembly,因此已经过时。可能存在编译到 WebAssembly 中的哈希函数,它们击败了纯 JS 实现。如果有人想更新此基准,欢迎向我的基准存储库提出拉取请求!


我对各种散列算法进行了基准测试,这是我发现的最快的选项:

  • 如果您只需要 32 位摘要,请使用iMurmurHash。请注意,这将在大约 2**14 (16,000) 次散列后给您带来冲突。

  • 如果您需要超过 32 位,请使用SparkMD5 。我没有找到快速的 64 位或 128 位 Murmur 实现,但 SparkMD5 速度惊人(75 MB/秒)。

    • 如果您需要增量更新,请考虑在将字符串提供给 SparkMD5 之前将它们加入更大的块中,因为 SparkMD5 的增量散列似乎受到一些中等开销的影响。

这些建议适用于纯 JavaScript。我用字符串对它们进行了基准测试,但 SparkMD5 也使用 ArrayBuffers。


如果你想在 Node 上快速散列模块,你的最佳选择略有不同:

  • 如果您正在对缓冲区进行哈希处理:使用带有 MD5 算法的内置加密模块。

    • 例外情况是:如果您不需要增量散列,并且需要超过 500 MB/秒的吞吐量,并且可以使用本机 npm 依赖项,请使用murmurhash-native以获得额外的性能。我没有测试小于 128 位的摘要大小,因为即使使用 128 位,散列也非常快,不太可能成为瓶颈。

      (请注意,murmurhash-native 在技术上支持增量哈希,但在这种模式下它比 Node 内置的 MD5 算法慢。)

  • 如果您非增量地散列单个字符串,请将其转换为 Buffer 并查看前面的要点。

  • 如果您以增量方式散列字符串:

    • 如果只需要 32 位,请使用 iMurmurHash。请注意,这将在大约 2**14 (16,000) 次散列后给您带来冲突。

    • 如果您需要超过 32 位:使用带有 MD5 算法的内置加密模块。

      • 我还建议您尝试将字符串连接到更大的块中,因为当您将字符串传递给加密模块时,它们会隐式转换为缓冲区,并且每个缓冲区的创建都非常慢。缓冲区创建和字符串连接通常会成为性能瓶颈,因为相比之下,本机散列函数非常快。
于 2017-02-06T17:35:18.627 回答