【问题标题】:Should I be concerned about .NET dictionary speed?我应该担心 .NET 字典的速度吗?
【发布时间】:2010-12-26 13:40:09
【问题描述】:

我将创建一个使用字典查找和插入的项目。这有什么需要担心的吗?

另外,如果我做基准测试之类的东西真的很糟糕,那么用其他东西替换字典的最佳方法是什么?使用带有“散列”键的数组会更快吗?但这对插入时间没有帮助吗?

另外,我不认为我在进行微优化,因为这确实会成为生产服务器上代码的重要组成部分,所以如果这需要额外的 100 毫秒来完成,那么我们将寻找新的方法来完成处理这个(事情。

【问题讨论】:

标签: c# arrays optimization dictionary


【解决方案1】:
  1. 正在进行微优化。你还有工作代码吗?请记住,“如果它不起作用,那么 快速 它不起作用并不重要。” (Mich Ravera)http://www.codingninja.co.uk/best-programmers-quotes/.

    您不知道瓶颈在哪里,而且您已经专注于 Dictionary。如果问题出在其他地方怎么办?

  2. 您如何知道 Dictionary 类是如何实现的?也许它已经使用了带有散列键的数组!

附:它实际上是“.NET 字典”,而不是“C# 字典”,因为 C# 只是使用 框架 的几种编程语言之一。

【讨论】:

  • +1 用于调用过早优化...您无法优化尚未编写的代码
  • 过早优化的另一个 +1。我非常同意我写了一条新评论,除了支持答案并点击戴夫评论上的向上箭头。
  • “如果它不起作用,它不起作用的速度有多快都没关系。” stackoverflow.com/questions/58640/great-programming-quotes/…
  • 如果它会影响应用程序的设计,这不是“过早的优化”。您不想编写一个应用程序,然后在中途意识到您的设计是错误的并且您必须重写它。人们如此快速地反省断章取义的引用......
  • 有一个视频,youtube.com/watch?v=aAb7hSCtvGw,我曾经和 Joshua Bloch 一起看到过,在某些情况下,在性能成为问题之前考虑它是多么值得(我认为它大约是一半)。来自伟大的编程报价 CW - “数周的编码可以节省您数小时的计划时间。”
【解决方案2】:

您好,我将创建一个项目 这将使用字典查找和 插入相当多。这是什么东西 需要担心吗?

是的。预先考虑性能因素总是明智的。

您的关注应该采取如下形式:您的关注应该鼓励您编写现实的、以用户为中心的性能规范。它应该鼓励您尽早开始编写性能测试并经常运行它们,这样您就可以看到对产品的每一次更改如何影响性能。这样,当代码更改导致影响用户的性能更改时,您将立即收到通知。它应该鼓励您经常运行配置文件,以便您根据经验测量而不是随机猜测和预感来推理性能。

另外,如果我进行基准测试等 它真的很糟糕,那是什么 用替换字典的最佳方法 还有什么?

最好的方法是构建一个合理的抽象层。如果您有一个代表“插入”和“查找”抽象数据类型的类(或接口),那么您可以在不更改任何调用者的情况下替换其内部。

请注意,添加抽象层本身会降低性能。如果您的分析表明抽象层过于昂贵,如果每次调用额外的几纳秒太多,那么您可能不得不摆脱抽象层。同样,该决定将由真实世界的性能数据驱动。

将使用带有“散列”的数组 键甚至更快?那不会 对插入时间有帮助吗?

您和阅读本文的任何人都不可能知道哪个更快,除非您以两种方式编写它,然后在在实际条件下以两种方式对其进行基准测试。在“实验室”条件下进行会扭曲您的结果;您需要了解当 GC 处于实际内存压力下时事情是如何工作的,等等。你不妨问问我们明年的肯塔基赛马哪匹马跑得更快。如果我们只看比赛形式就知道答案,我们都已经很有钱了。您不可能期望任何人知道在未指定的条件下,两个完全假设的、未编写的代码中的哪一个会更快!

【讨论】:

  • 我同意并在实践中使用过这种预先使用接口/抽象的方法,然后根据性能测试指示将其删除。而且我会添加不要过早删除该界面!它可能会让您在设计过程中失去设计灵活性,从而导致大量重构……我也经历过。
  • 我会在 2010 年肯塔基赛马比赛中猜测并说“超级救星”。
【解决方案3】:

Dictionary<TKey, TValue> 类实际上是作为哈希表实现的,这使得查找速度非常快(接近 O(1))。请参阅the API documentation 了解更多信息。我怀疑你自己可以做出更好的实现。

【讨论】:

  • 这里不是毛茸茸的裤子先生,但 O(1) 并不意味着它很快,它只是意味着它是恒定的时间。但是那个恒定的时间可能很长也可能很短。也就是说,O(1) 在实践中往往很快。
【解决方案4】:

等待看看您的应用程序的性能是否低于预期
如果是,则使用分析器来确定字典查找是否是问题的根源
如果是,则使用代表性数据进行一些测试,看看是否另一种选择列表会更快。

简而言之 - ,一般来说,在您遇到问题之前,您不应该担心实现细节的性能。

【讨论】:

    【解决方案5】:

    我会做一个 Dictionary、HashTable(.NET 中的 HashSet)的基准测试,也许还有一个自制的类,看看哪个在您的典型使用条件下效果最好。

    通常我会说这很好(在此处插入 StackOverflow 最喜欢的早泄报价),但如果这是应用程序的核心部分,Benchmark、Benchmark、Benchmark。

    【讨论】:

    • 字典 应该总是优于哈希表。即使 Dictionary 不存在,.NET HashTables 也是一个坏主意 :)
    • 应该吗?我的意思是 HashSet 我从不喜欢 .Net 中的旧 HashTables
    【解决方案6】:

    我能想到的唯一问题是字典的速度依赖于具有相当快的 GetHashCode 方法的键类。查找和插入非常快,所以你应该不会有任何问题。

    关于使用数组,Dictionary 类已经这样做了。实际上它使用了两个数组,一个用于键,一个用于值。

    如果您对 Dictionary 有任何性能问题,那么为任何类型的存储创建一个包装器将非常容易,它具有与 Dictionary 相同的方法和行为,以便您可以无缝地替换它。

    【讨论】:

      【解决方案7】:

      我不确定是否有人真正回答了这部分:

      另外,如果我进行基准测试等 它真的很糟糕,那是什么 用替换字典的最佳方法 还有什么?

      为此,请尽可能将您的变量声明为IDictionary<TKey, TValue>。这是 Dictionary 派生的主界面。 (我假设如果您非常关心性能,那么您就不会考虑非泛型集合。)然后,将来,您可以更改底层实现类,而无需更改任何使用它的代码字典。例如:

      IDictionary<string, int> myDict = new Dictionary<string, int>();
      

      【讨论】:

      • @Morbo:Eric Lippert 说,“做到这一点的最好方法是构建一个合理的抽象层。”在他的回答中。
      【解决方案8】:

      如果您的应用程序是多线程的,那么性能的关键部分将是正确同步此 Dictionary。

      如果它是单线程的,那么几乎可以肯定瓶颈会在其他地方。例如从您正在阅读它们的任何地方读取这些对象。

      【讨论】:

        【解决方案9】:

        我使用 Dictionary for UDP 中继服务器。每次数据包到达时,它都会执行 Dictionary.ContainsKey 和 Dictionary[Key] ,并且效果很好(大量客户端)。我在制作这个东西时有顾虑,但事实证明这是我最不应该担心的事情。

        【讨论】:

          【解决方案10】:

          看看C# HybridDictionary Usage

          HybridDictionary Class

          这个类推荐用于案例 其中 a 中的元素个数 字典不详。它需要 提高性能的优势 一个 ListDictionary 的小 集合,并提供 切换到一个的灵活性 处理更大的哈希表 集合比 ListDictionary 好

          【讨论】:

          • 对我来说,非泛型等于非首发。不过,我确实想知道为什么他们从未制作过此类的通用版本。
          【解决方案11】:

          您可以考虑使用C5 库。我发现它非常快速且经过精心设计。 stackoverflow 上的其他人也发现了同样的情况。使用 C5,您可以选择使用通用类型接口(带有大写字母 I),或直接使用下面的数据结构。自然地,接口允许您交换不同的实现,但我在性能测试中发现接口会花费您。

          【讨论】:

            【解决方案12】:

            您可能想查看 System.ObjectModel 中的 KeyedCollection 类。根据 MSDN 的描述,“为集合提供抽象基类,其键嵌入在值中。”

            【讨论】:

            • 猜猜KeyedCollection是基于什么类型来提供分期的O(1)密钥检索?..
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-02-19
            • 2013-03-20
            相关资源
            最近更新 更多