比较散列策略

总览

编年史有许多用于哈希的实现,包括City和Murmur。 它也有自己的香草哈希,但是如何进行测试?

什么是香草哈希?

Vanilla Hash设计得尽可能简单,并且针对Orthogonal Bits测试进行了优化(请参见下文),并与City 1.1和Murmur 3哈希策略进行了比较。

这是用新数据填充64字节/ 256字节缓冲区并生成64位哈希值的99%延迟。 JMH用于执行测量。 请参阅Main64bytesMain256bytes

散列,策略 64字节99%瓦片 256字节99%瓦片
香草 67 ns 112毫微秒
城市1.1 90纳秒 182 ns
杂音3 104毫微秒 211 ns

您可以执行哪些测试来检查哈希策略是否良好?

您可以执行许多简单的测试。 测试无法识别出良好的哈希,但可以将哈希显示为不良哈希。 通过一项测试可能意味着它将无法通过另一项测试。

在每种情况下,都使用不同的随机起点运行多个测试。 分数为第99%,即最差的1%。 这是因为您不需要在某些时间或平均情况下有效的哈希。 您需要一种大多数情况下都可以使用的产品。 (在所有情况下,您都可以发明任何特定散列都将分解的病理情况)

为了保持一致性,分数越低越好。 测试的构造应使得分为0表示测试已损坏。

在每个测试中,使用8,192位或1024 KB的输入,一次切换一位。 根据这些输入,将生成8,192 x 64位哈希。

但是,对于随机测试,采用了一系列随机的64位值。 这些对于了解所测试的散列策略有多少是有用的。

哈希表掩码

在此测试中,每个哈希的模数为16,384(哈希数的两倍),并且报告了冲突数。 大多数哈希策略在此测试中效果很好。

雪崩分数

在此测试中,将每个散列与前一个散列(前一位进行切换)进行比较,以查看任何给定位被翻转的可能性。 理想值为50%,与50%的差异之和为报告的最差1%。

延迟速度

在此测试中,记录了执行哈希所需的时间,并报告了最差的1%延迟。

正交钻头

该测试的目的是确保所有哈希具有的位与生成的其他所有哈希均尽可能不同。 除了64位数字外,请考虑8个皇后问题。 理想的情况是每个数字都具有与其他每个数字不同的相同位数,并且位数应尽可能高。

在此测试中,将每个哈希与每个其他哈希进行比较。 对不同的位数进行计数。 如果不同位数小于18,则给出2 ^(17-n)的惩罚分数。 位数越少,则指数级的惩罚越大。 如果映射到其他8K哈希值的任何8K哈希值的差异小于5位,则即使所有其他对都很好,这也是失败的。

我称其为正交位测试,因为您可以将64位数字建模为64位的位向量。 理想情况下,您希望产生的所有散列之间的角度尽可能大。

在所有测试中,此测试显示具有HashMap.hash(int)的String.hashCode()与其他哈希策略之间的最大差异。

测试String.hashCode()

String.hashCode()是一个非常差的哈希,尤其是对于低位 。 它是标准的,不能更改或破坏向后兼容性。 但是,这不一定是问题,因为HashMap使用agitate函数,该函数会降低一些较高的位以随机化较低的位。

int hash(int h) {
    // This function ensures that hashCodes that differ only by
    // constant multiples at each bit position have a bounded
    // number of collisions (approximately 8 at default load factor).
    h ^= (h >>> 20) ^ (h >>> 12);
    return h ^ (h >>> 7) ^ (h >>> 4);
}

结果

CheckMain类对每种哈希策略运行一套测试。

VANILLA
Orthogonal bits: 99%tile score: 6066
Speed: The 99%tile for latency was 0.223 us
Avalanche: The 99%tile of the drift from 50% was 0.55%
Mask of Hash: 99%tile collisions: 1815

CITY_1_1
Orthogonal bits: 99%tile score: 7395
Speed: The 99%tile for latency was 0.267 us
Avalanche: The 99%tile of the drift from 50% was 0.55%
Mask of Hash: 99%tile collisions: 1817

MURMUR_3
Orthogonal bits: 99%tile score: 7524
Speed: The 99%tile for latency was 0.378 us
Avalanche: The 99%tile of the drift from 50% was 0.54%
Mask of Hash: 99%tile collisions: 1815

STRING32
Orthogonal bits: 99%tile score: 295906433
Speed: The 99%tile for latency was 1.580 us
Avalanche: The 99%tile of the drift from 50% was 1.02%
Mask of Hash: 99%tile collisions: 1814

STRING64
Orthogonal bits: 99%tile score: 1939167
Speed: The 99%tile for latency was 1.520 us
Avalanche: The 99%tile of the drift from 50% was 0.61%
Mask of Hash: 99%tile collisions: 1816

STRING32_WITHOUT_AGITATE
Orthogonal bits: 99%tile score: 879390386
Speed: The 99%tile for latency was 1.573 us
Avalanche: The 99%tile of the drift from 50% was 3.53%
Mask of Hash: 99%tile collisions: 6593

RANDOM
Orthogonal bits: 99%tile score: 7444
Speed: The 99%tile for latency was 0.058 us
Avalanche: The 99%tile of the drift from 50% was 0.53%
Mask of Hash: 99%tile collisions: 1817

SECURE_RANDOM
Orthogonal bits: 99%tile score: 7449
Speed: The 99%tile for latency was 0.861 us
Avalanche: The 99%tile of the drift from 50% was 0.54%
Mask of Hash: 99%tile collisions: 1816

SEEDED_VANILLA
Orthogonal bits: 99%tile score: 6000
Speed: The 99%tile for latency was 0.219 us
Avalanche: The 99%tile of the drift from 50% was 0.55%
Mask of Hash: 99%tile collisions: 1814

SEEDED_CITY_1_1
Orthogonal bits: 99%tile score: 7313
Speed: The 99%tile for latency was 0.270 us
Avalanche: The 99%tile of the drift from 50% was 0.54%
Mask of Hash: 99%tile collisions: 1813

SEEDED_MURMUR_3
Orthogonal bits: 99%tile score: 7404
Speed: The 99%tile for latency was 0.359 us
Avalanche: The 99%tile of the drift from 50% was 0.53%
Mask of Hash: 99%tile collisions: 1810

注意:香草杂种种子是Chronicle Enterprise的一部分

结论

Vanilla,City和Murmur哈希是最快的。

尽管String.hashCode()很简单,但每个字符的乘法运算却很昂贵。 相比之下,所有其他字节使用long一次处理8个字节。 与STRING32相比,请参阅STRINGS32_WITHOUT_AGITATE。 HashMap使用更高版本。

即使在avalanche测试中,带有搅动的32位String hashCode()也表现不佳。 在SMHasher中,该测试的得分超过1%被视为失败。

哈希掩码测试虽然简单,但在所有情况下都表现良好。 例外是String.hashCode(),如上所述,它没有非常随机的低位。

我发现有趣的是,正交测试得分有何不同。 前三个哈希策略再次持续较低。 甚至String.hashCode()的64位版本在产生散列方面也有很大的变化,只有不到18位的不同,实际上很多位是相同的。

免责声明

香草哈希已针对正交钻头测试进行了优化。 因此,获得更好的结果也就不足为奇了。 这并不意味着Vanilla Hash比City或Murmur好。 这可能仅表示对“正交位”测试最好。

翻译自: https://www.javacodegeeks.com/2015/08/comparing-hashing-strategies.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值