【问题标题】:Multi level dictionary Performance多级词典性能
【发布时间】:2016-02-07 05:12:08
【问题描述】:

最近,我开始从事一个 C# .NET 项目,该项目需要在内存中保留一个单词字典。

我的第一个方法是创建一个

Dictionary<string, string>

(其中 Key 是单词,Value 是定义)。

效果很好,过了一段时间我决定尝试使用“buckets”并尝试了一个

Dictionary<char, Dictionary<string, string>>

char 是内部字典中单词的第一个字母。

我的问题是:我真的通过应用此更改获得了性能提升吗? (并使代码更复杂)

我知道字典应该是 O(1),所以理论上 5 个单词或 200 万个单词是相同的。通过添加多个级别,我会重复查找时间。

谢谢!

【问题讨论】:

  • 从表面上看,这可能会使事情变慢。我建议你自己做一些性能测试来确定。
  • 首先,正如@user5151179 指出的那样,找出答案的唯一方法就是实际测量它。其次,也许更重要的是:在考虑优化之前,看看您是否真的性能问题。
  • Horses 由 Eric Lippert 回答您的问题。如果您仍有问题,请阅读并更新帖子
  • 恕我直言字典已经在内部使用了存储桶。在此处查看源代码:referencesource.microsoft.com/#mscorlib/system/collections/…
  • 感谢 gdir,这正是我最初的想法,这就是字典的工作方式,具有恒定的访问时间查找表。我不知道字典如何计算要使用的存储桶。也许通过自己做最初的桶,我会“帮助”它。

标签: c# .net performance dictionary optimization


【解决方案1】:

这里有很多很多因素在起作用。通过按字母拆分数据,您可以将更多查找注入到需要由 CPU 缓存的不相关类型中。相反,您更有可能破坏缓存并获得糟糕的性能。

另一方面,如果您有很多条目相对平均地分布在它们的第一个字母上,并且如果您不均匀地查找而是只关注几个字母,那么您就是可能会提高查找性能。

最后一点,我不知道您从哪里得到字典查找(或任何字典)是 O(1) 的想法,您可能需要考虑查看它。这势必会让你的决定不正确。

【讨论】:

  • 感谢 Blindy,因此作为对您的回应:Hashtable 类(以及任何 Dictionary)具有 O(1) 性能,但内存使用量略有下降(查找表)。 O(1) 表示获取值的时间(如果没有冲突)是常数。
  • 这里重要的是“如果没有冲突”部分。字典查找不是 O(1)。您可以争辩说它乐观地 O(1),但这是一个通常无用的指标。​​
  • 没错!那么像我提议的那样有助于避免碰撞吗?你认为会发生什么? (当然这都是理论上的,我可以像一些 cmets 建议的那样去测试它,但我希望能够解释我得到的结果)。使用更小的存储桶会提高访问查找表的恒定时间吗?
  • 它不会,因此是“最后一点”。这是无关的。这是对您的信念的答复,我引用了“我知道字典应该是 O(1)”。从来没有对任何字典实现有过这样的要求。
【解决方案2】:

答案是——不,你不会通过拆分散列表来提高它的性能。而且,正如您所指出的,您总是会进行多次查找。

要提高性能,您需要减少碰撞次数。假设散列函数是相同的,你唯一可以改变的是负载因子。与往常一样,速度是以空间为代价的。

忽略开销,在同一个空间中,您可以创建一个包含 1,000 个存储桶或十个存储桶的表 - 包含 100 个存储桶。在其中放置 1,000 个项目将为您提供 1.0 的负载因子,作为一个 平均值 1.0 的小家伙。 “幸运”表将有更好的表现,其他 - 值得。添加一个额外的查找时间...

【讨论】:

  • 感谢弗拉德,我正在编写测试以查看它的执行情况,并在完成后分享结果。到时候我会选择正确的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-14
  • 1970-01-01
  • 2012-04-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多