【问题标题】:Performance of Guava's ImmutableSet.containsGuava 的 ImmutableSet.contains 的性能
【发布时间】:2012-09-16 09:51:09
【问题描述】:

Guava 的ImmutableSet 在我关于contains 的基准测试中似乎表现很差。对于某些尺寸,它甚至比 List 慢得多:

  size            benchmark         ns linear runtime
100000         ListContains  110279.54 ==
100000          SetContains       7.15 =
100000 ImmutableSetContains   76716.47 =
200000         ListContains  275367.66 =====
200000          SetContains       7.34 =
200000 ImmutableSetContains  322185.50 ======
500000         ListContains  935210.10 ====================
500000          SetContains       7.79 =
500000 ImmutableSetContains 1382765.76 ==============================

基本上,我用几千个负整数填充一个集合,并用非负整数测试包含。代码很琐碎,但在小文本区域粘贴有点太长了,所以请看here

我想知道这里发生了什么。可能,我遇到了一些退化的情况,尽管我显然没有尝试这样做。或者,也许我刚刚打破了基准。否则,我想知道它是否可以并且应该被修复。


解决方法是通过replacing更改涂抹功能

hashCode ^= (hashCode >>> 20) ^ (hashCode >>> 12);
return hashCode ^ (hashCode >>> 7) ^ (hashCode >>> 4);

通过

return C2 * Integer.rotateLeft(hashCode * C1, 15);

这需要大约相同的时间并且可能有一些缺点,但通过很好地散布散列解决了当前的问题。

【问题讨论】:

  • 是的,你遇到了一个严重退化的案例。但这可能不应该出现在 SO 上;应该是问题报告。
  • 我现在明白了...我必须先写问题,但实际上很明显。
  • @Louis Wasserman:我几乎可以肯定我搞砸了(发生了其他奇怪的事情);这就是为什么我想先在这里问。我想我找到了一个不错的解决方案。

标签: set guava immutability caliper


【解决方案1】:

解释其实很简单。想象一下,对于某些N,整数位于集合M = {0, 1, ..., N-1} 中,这是2 的幂。哈希也是如此,因为Integer.hashCode 是如何定义的。哈希通过与this one 相同的函数smear 进行处理,以便在某些常见情况下最大限度地减少最低位的冲突。

2*N 大小的表被分配,M 的成员被放入其中。由于smear 只涉及右移,它将M 映射到自身,这意味着表格的连续范围被填充。因此,假设表左半部分的所有插槽都已使用,而另一半未使用。

contains(o) 被调用时,搜索开始于一个位置由o.hashCode() 确定的位置。如果找到o,则结果为true,如果找到空槽,则结果为false。否则,搜索继续到另一个槽。为了尽量减少缓存未命中,使用linear probing

当我们很不幸地从第一个使用的槽开始搜索时,它们都必须被遍历,这意味着N 步骤。从随机位置开始意味着N/4 平均步数。

在我的基准测试中发生的情况与上面的不完全一样,但其性能不佳的原因是相同的。将大小设为 2 的幂会使问题变得更糟。

【讨论】:

  • 是的,这基本上涵盖了它。即使我们使用例如二次探测,它仍然几乎一样糟糕。我想真正的问题是涂抹应该做更多的涂抹?
  • @Louis Wasserman:二次探测将在与sqrt(N) 成正比的时间到达未使用的一半,而不是N,但它仍然与1 相差太远,并且由于缓存未命中而效率很低。但是,我建议切换到线性探测和更强探测的某种组合,因为线性探测很容易失败。是的,涂抹可以扩展,这样上述问题就会消失,property promised 仍然存在。我应该提交错误并在那里解释吗?
  • 这是我在进行基准测试并获得硬数据之前的想法。据我所知,二次探测在理论上可能会有所帮助,但实际上并非如此。但是,是的,提交一个错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多