【问题标题】:Dictionary<> performance on sequential vs random字典<>在顺序与随机上的表现
【发布时间】:2011-10-04 17:02:49
【问题描述】:

我正在使用 Dictionary 来存储数百万个条目。这些数字被添加到大量的序列号中。

我记得一些散列算法无法按顺序添加键。

.Net 是这种情况吗?
如果是这样,我有什么选择? (任何整洁的库?)

数据一旦添加就相当静态。通过随机化器添加数据是否值得?

PS 我已经签出:

【问题讨论】:

    标签: .net algorithm hash dictionary


    【解决方案1】:

    查询的性能应该独立于将键添加到哈希表中的顺序。即使存在冲突,插入元素也很容易通过链接进行 O(1) 分摊。

    您是否实际测量过性能问题?如果没有,请不要费心进行更改。如果是这样,请考虑编写一个针对顺序索引进行优化的类。

    【讨论】:

    • 在极端情况下,性能实际上取决于插入的顺序。每个桶都有自己的链表。如果所有项目都落入同一个桶中,则查找最后一个插入的项目几乎是瞬时的,但对于第一个插入的项目,它将是 O(N)。当然,这意味着你有可怕的哈希函数。此外,在存在冲突的情况下不能保证插入 O(1),因为需要检查该项目是否已经在字典中。该检查与存储桶的大小成线性关系。
    【解决方案2】:

    注意:我所说的“序列”是指递增一的数字序列。

    实际上,如果添加到字典中的唯一键是按顺序排列的(没有重复或间隙),那是最好的情况。在 .Net 的当前实现中(可能随时更改,因此您不应依赖其中任何一个),所有数字序列的 long.GetGashCode() 返回一个数字序列。并且桶数是计算字典的模容量。这意味着在这种情况下,您可以保证不会发生冲突。

    如果您有多个长度相同的序列,最坏的情况是它们都发生冲突,并且每个使用的存储桶将包含每个序列的一个项目。不过,这不太可能。在一般情况下,您会遇到一些冲突,但平均检索时间很可能仍为 O(1)。

    (上面有一个小小的谎言。对于每一次跨越 32 位边界,一个序列的哈希码序列将有一个数字的间隙,因为 long.GetHashCode() 的实现方式。 )

    【讨论】:

    • 这同样适用于 Dictionary 吗?
    • @Tedd,是的。 int.GetHashCode() 直接返回那个int
    【解决方案3】:

    对于这么多项目,字典可能会产生大量开销,并且它依赖于良好的哈希分布以获得理想的性能。

    您可能想针对其他方法运行一些基准测试,是否可以简单地分配一个数组并使用键作为索引?比如 object[long],如果你只有 0 到 100 万个可能的值,那么数组占用的空间不到 8MB,而且比 Dictionary 快得多。

    如果您不能直接这样做,您可以查找唯一的 long 到 int 索引吗?例如,有一个字典可以让您将 long 转换为一个不断增加的 int,当一个新的 long 出现时,您在它被分配到数组中的位置之前还没有看到。

    或者可能使用更复杂的方法来处理锯齿状数组,例如 object[sequenceInt][uniqueIndexInt]。这真的取决于您以后将如何访问数据

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-18
      • 1970-01-01
      • 2016-06-19
      • 1970-01-01
      • 2016-04-15
      • 1970-01-01
      相关资源
      最近更新 更多