【问题标题】:Is there a limit to entries in a Dictionary<>?Dictionary<> 中的条目是否有限制?
【发布时间】:2011-03-28 12:08:46
【问题描述】:

我有大约 3000 个不同的文件需要整理,并在游戏期间的不同时间检索。

我创建了自己的变量结构。 我正在考虑创建一个“字典” 在我的应用程序开始时,只需在游戏开始前加载我的所有文件。

我想知道性能:包含这么多条目的字典会导致我的应用程序变慢吗? 大字典会使“TryGetValue”和“ContainsKey”运行速度变慢吗?

感谢您的建议!

【问题讨论】:

    标签: c# silverlight performance dictionary idictionary


    【解决方案1】:

    TryGetValue 和 ContainsKey 在该大小下应该非常快,只要键具有良好分布的哈希值。

    字典具有可索引数量的“桶”。当它通过键添加或查找值时,它将获取 GetHashCode() 返回的值,再次对其进行哈希处理以小于存储桶的数量(通常像模一样简单,但未定义实现),并查看相关的存储桶。

    存储桶当前将包含零个或多个项目。字典将使用 .Equals() 将每个项目与键进行比较。

    找到正确存储桶的第一步将是常数时间 O(1)。将键与桶中的键进行比较的第二位将在线性时间 O(n) 中进行,其中 n 仅与该桶中的项目数有关,与整个集合无关。

    通常每个桶中的项目应该很少(桶的数量会增加以尽量保持这种情况),因此操作基本上是恒定的时间。

    但是,如果您的哈希码执行不力,那么同一个存储桶中将会有很多键。时间复杂度将越来越接近 O(n),这可以通过尝试使用故意错误的 GetHashCode 每次只返回 0 的对象来看出。在更糟糕的情况下,它比 List 更糟糕,因为 List 也是 O(n),但 Dictionary 的开销更大。

    这是否意味着您应该担心?不,即使是相对简单的散列方法也应该给出相对好的结果。如果您使用的是字符串键,那么它可能已经足够好了。如果您使用的是简单的内置类型,则更是如此。

    如果您确实发现访问字典很慢,那么您需要注意这一点并修复 GetHashCode() 方法或创建一个 IEqualityComparer(它允许您为 GetHashCode() 和 Equals() 定义外部规则用于字典、哈希集等)。

    但很可能,3000 不算什么,没关系。

    【讨论】:

      【解决方案2】:

      Dictionary&lt;&gt; 有 3000 个条目。这不会是放缓的根源。

      在启动时将 3000 个不同的文件读入内存,另一方面,很慢。最好只在需要时将文件读入内存,然后将它们保存在内存中以供后续访问。

      【讨论】:

      • 既然他提到了一个游戏,那一般的规则可能不适用。根据它们加载的时间点和它们的大小,最好将它们加载到启动启动屏幕后面,而不是在艾什试图击杀一个死神时......
      • 可以说,他们可以在启动期间生成一个后台线程来执行该进程。
      【解决方案3】:

      不,不会的。它会消耗内存,但 TryGetValueContainKey 应该很快,因为字典是一个哈希表,通过键访问元素是恒定的,它不依赖于元素的数量。

      【讨论】:

        【解决方案4】:

        为字典键类型提供哈希码算法可以将哈希码相对均匀地分布在 Int32 空间中,哈希码查找不受字典大小的影响。

        更多详情请见http://en.wikipedia.org/wiki/Hashtable#Performance_analysis

        【讨论】:

        • +1 指出这只有在哈希没有被破坏的情况下才有效。
        【解决方案5】:

        .NET 中的字典使用哈希表查找方案,因此添加条目对查找性能的影响很小(如果有的话)。您将遇到的唯一问题可能是内存使用情况。包含 3000 个项目的字典将消耗大约 3000 倍于键和值类型所使用的存储空间。如果它只是一个没有巨大二进制 blob 的简单结构,那么 3000 是非常小的。

        【讨论】:

          【解决方案6】:

          您的瓶颈将不是字典的性能,而是读取 3000 个文件。

          【讨论】:

            【解决方案7】:

            与计算机的大多数事情(尤其是性能)一样,“It Depends (tm)”

            这一切都取决于字典的实现。

            它可以作为二叉树来完成,在这种情况下查找应该是 O(log2 N),这意味着查找时间随着字典大小的增长而缓慢增长。

            它可以作为一个哈希表来完成,理论上它是 O(1),这意味着无论字典的大小如何,查找总是需要相同的时间,但这是理论上的,并且取决于桶的数量和哈希码的质量。如果许多项目最终在同一个存储桶中,需要线性搜索,那么随着字典的增长,事情会大大减慢。

            但是,字典必须增长到超过 3000 几个数量级才能看到明显的差异。

            【讨论】:

            • Dictionary 被指定为使用哈希表。
            猜你喜欢
            • 1970-01-01
            • 2012-02-07
            • 2019-04-11
            • 1970-01-01
            • 2016-09-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多