JavaScript for Files中的快速低冲突非加密哈希

Eri*_*son 6 javascript hash html5 fileapi

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

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

总的来说,SparkMD5可以满足我的需求,但对于大型文件,它可能需要一段时间才能获得我的哈希值(300MB文件大约需要30秒).我希望减少这一点.我不是那么了解哈希函数,所以我不想寻找一些东西,并且理想地寻找已经实现的库.

Jo *_*iss 12

更新(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 算法的内置加密模块。

      • 我还建议您尝试将字符串连接成更大的块,因为当您将字符串传递给加密模块时,字符串会隐式转换为缓冲区,并且每个缓冲区的创建都非常慢。性能通常会受到缓冲区创建和字符串连接的瓶颈,因为相比之下,本机哈希函数非常快。