XxHash: 非常快速的非加密哈希算法

XxHash: 非常快速的非加密哈希算法

( 如需查看英文版本,请 点击这里 )

xxHash-极快的哈希算法

xxHash是一种非常快速的哈希算法,在RAM速度限制下运行。它成功地完成了SMHasher测试套件,用于评估哈希函数的碰撞、分散和随机性。代码具有很高的可移植性,哈希在所有平台上都是相同的(little/big-endian)。

Benchmarks

参考系统使用Inteli7-9700Kcpu,运行UbuntuX64 20.04。开源基准测试程序是用clangv10.0使用-O3标志编译的。

Hash Name

Width

Bandwidth (GB/s)

Small Data Velocity

Quality

Comment

XXH3 (SSE2)

64

31.5 GB/s

133.1

10

XXH128 (SSE2)

128

29.6 GB/s

118.1

10

RAM顺序读取

N/A

28.0 GB/s

N/A

N/A

for reference

City64

64

22.0 GB/s

76.6

10

T1ha2

64

22.0 GB/s

99.0

9

稍差的碰撞

City128

128

21.7 GB/s

57.7

10

XXH64

64

19.4 GB/s

71.0

10

SpookyHash

64

19.3 GB/s

53.2

10

Mum

64

18.0 GB/s

67.0

9

稍差的碰撞

XXH32

32

9.7 GB/s

71.9

10

City32

32

9.1 GB/s

66.0

10

Murmur3

32

3.9 GB/s

56.1

10

SipHash

64

3.0 GB/s

43.2

10

FNV64

64

1.2 GB/s

62.7

5

雪崩特性差

Blake2

256

1.1 GB/s

5.1

10

Cryptographic

SHA1

160

0.8 GB/s

5.6

10

加密但已损坏

MD5

128

0.6 GB/s

7.8

10

加密但已损坏

1:小数据速率是对小数据的算法效率的粗略评估。有关更详细的分析,请参阅下一段。

2:有些算法比RAM速度快。在这种情况下,只有当输入数据已经在CPU缓存(L3或更高)中时,它们才能达到全速。否则,它们会在RAM速度限制下达到最大值。

  • Small data

对大数据的性能只是图片的一部分。哈希在哈希表和bloom过滤器等构造中也非常有用。在这些用例中,经常散列大量的小数据(从几个字节开始)。在这种情况下,算法的性能可能会有很大的不同,因为算法的某些部分,例如初始化或终结,变成了固定成本。分支mis-prediction的影响也变得更加明显。

XXH3的设计在长输入和小输入方面都具有出色的性能,可以在下图中观察到这一点:

有关更详细的分析,请访问wiki:https://github.com/Cyan4973/xxHash/wiki/Performance-comparison#benchmarks-concentrating-on-small-data-

Quality

速度不是唯一重要的属性。产生的散列值必须尊重优秀的分散性和随机性,这样它的任何sub-section都可以用来最大限度地扩展一个表或索引,并将碰撞量减少到最小理论水平,遵循生日悖论。

xxHash已经用austinappleby的优秀SMHasher测试套件进行了测试,并通过了所有测试,确保了合理的质量水平。它还通过了来自新的SMHasher分支的扩展测试,具有附加的场景和条件。

最后,xxHash提供了自己的大规模碰撞测试程序,能够生成和比较数十亿个哈希来测试64-bit哈希算法的极限。在这方面,xxHash也有很好的效果,符合生日悖论。wiki中记录了更详细的分析。

  • Build modifiers

可以在编译时设置以下宏来修改libxxhash的行为。它们通常在默认情况下被禁用。

  • XXH_INLINE_ALL:使所有函数inline,实现直接包含在xxhash.h中。内联函数有助于提高小按键的速度。当密钥长度被表示为编译时常数时,它非常有效,性能改进在+200%范围内。有关详细信息,请参阅本文。
  • XXH_PRIVATE_API:与XXH_INLINE_ALL的结果相同。仍然可用于遗留支持。该名称强调XXH_*符号将不会导出。
  • XXH_NAMESPACE:在所有符号前面加上XXH_NAMESPACE的值。此宏只能使用可编译字符集。当xxHash的源代码包含多个时,有助于避免符号命名冲突。客户机应用程序仍然使用常规函数名,因为符号是通过xxhash.h自动转换的。
  • XXH_FORCE_MEMORY_ACCESS:默认方法0使用可移植的memcpy()符号。方法1使用gcc-specificpacked属性,该属性可以为某些目标提供更好的性能。方法2强制执行未对齐的读取,这不符合标准,但有时可能是提取更好的读取性能的唯一方法。方法3使用byteshift操作,这最适用于那些不在没有byteswap指令的memcpy()big-endian系统的旧编译器
  • XXH_FORCE_ALIGN_CHECK:对齐输入时使用更快的直接读取路径。当哈希的输入在3264-bit边界上对齐时,当在无法从未对齐的地址加载内存的体系结构上运行时,或由于它而受到性能损失时,此选项可以显著提高性能。在具有良好的未对齐内存访问性能(对齐和未对齐访问的相同指令)的平台上,这是(稍微)有害的。此选项在x86x64aarch64上自动禁用,并在所有其他平台上启用。
  • XXH_VECTOR:手动选择一个向量指令集(在编译时默认为auto-selected)。可用的指令集有XXH_SCALARXXH_SSE2XXH_AVX2XXH_AVX512XXH_NEONXXH_VSX。编译器可能需要额外的标志来确保正确的支持(例如,linux上的gcc对于AVX2需要-mavx2,对于AVX512需要-mavx512f)。
  • XXH_NO_PREFETCH:禁用预取。仅限XXH3
  • XXH_PREFETCH_DIST:选择完善距离。仅限XXH3
  • XXH_NO_INLINE_HINTS:默认情况下,xxHash使用__attribute__((always_inline))__forceinline来提高性能,但以代码大小为代价。将此宏定义为1将所有内部函数标记为static,允许编译器决定是否内联函数。这在优化最小二进制大小时非常有用,并且在GCCClang上使用-O0-Os-Oz-fno-inline编译时自动定义。这还可以根据编译器和体系结构提高性能。
  • XXH_REROLL:通过不展开某些循环来减少生成代码的大小。对性能的影响可能会有所不同,这取决于平台和算法。
  • XXH_ACCEPT_NULL_INPUT_POINTER:如果设置为1,当输入是NULL指针时,xxHash的结果与zero-length输入相同(而不是取消引用segfault)。在每个哈希的开头添加一个分支。
  • XXH_STATIC_LINKING_ONLY:为静态分配提供对状态声明的访问。由于ABI更改的风险,与动态链接不兼容。
  • XXH_NO_LONG_LONG:删除依赖64-bit类型(XXH3XXH64)的算法编译。只编译XXH32。对于没有64-bit支持的目标(体系结构和编译器)很有用。
  • XXH_IMPORT:MSVC-specific:只应为动态链接定义,因为它可以防止链接错误。
  • XXH_CPU_LITTLE_ENDIAN:默认情况下,endianess由编译时解析的运行时测试确定。如果由于某种原因,编译器不能简化运行时测试,则会降低性能。可以跳过auto-detection,通过将这个宏设置为1,简单地声明体系结构是little-endian。将其设置为0状态big-endian

对于命令行界面xxhsum,还可以设置以下环境变量:

  • DISPATCH=1:根据本地主机,使用xxh_x86dispatch.c在运行时自动选择scalarsse2avx2avx512指令集。此选项仅对x86/x64系统有效。
  • 正在构建xxHash-使用vcpkg

您可以使用vcpkg依赖关系管理器下载并安装xxHash

git clone https://github.com/Microsoft/vcpkg.git

cd vcpkg

./bootstrap-vcpkg.sh

./vcpkg integrate install

./vcpkg install xxhash

vcpkg中的xxHash端口由Microsoft团队成员和社区贡献者保持最新。如果版本已过期,请在vcpkg存储库上创建问题或请求请求。

  • Example

最简单的示例调用XXHASH 64-bit变体作为one-shot函数,从单个缓冲器生成哈希值,并从C/C++程序调用:

#include "xxhash.h"

    (...)

    XXH64_hash_t hash = XXH64(buffer, size, seed);

}

流式变体涉及更多,但可以增量提供数据:

#include "stdlib.h"   /* abort() */

#include "xxhash.h"

XXH64_hash_t calcul_hash_streaming(FileHandler fh)

{

    /* create a hash state */

    XXH64_state_t* const state = XXH64_createState();

    if (state==NULL) abort();

    size_t const bufferSize = SOME_SIZE;

    void* const buffer = malloc(bufferSize);

    if (buffer==NULL) abort();

    /* Initialize state with selected seed */

    XXH64_hash_t const seed = 0;   /* or any other value */

    if (XXH64_reset(state, seed) == XXH_ERROR) abort();

    /* Feed the state with input data, any size, any number of times */

    (...)

    while ( /* some data left */ ) {

        size_t const length = get_more_data(buffer, bufferSize, fh);

        if (XXH64_update(state, buffer, length) == XXH_ERROR) abort();

        (...)

    }

    (...)

    /* Produce the final hash value */

    XXH64_hash_t const hash = XXH64_digest(state);

    /* State could be re-used; but in this example, it is simply freed  */

    free(buffer);

    XXH64_freeState(state);

    return hash;

}

  • License

库文件xxhash.cxxhash.hBSD授权的。实用程序xxhsumGPL授权的。

  • 其他编程语言

除了C参考版本之外,xxHash还可以从许多不同的编程语言中获得,这要感谢伟大的贡献者。它们列在这里。

  • Special Thanks

Takayuki Matsuoka,又名@t-mat,用于在xxh早期版本中创建xxhsum -c和一般支持

Mathias Westerdahl,又名@JCash,因为他介绍了XXH64的第一个版本

Devin Hussey,又名@easyaspi314,他对XXH3XXH128进行了出色的low-level优化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值