关于c#:我应该关注.NET字典的速度吗?

Should I be concerned about .NET dictionary speed?

我将创建一个使用字典查找和插入相当多的项目。这是值得关注的事情吗?

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

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


  • 您正在进行微优化。您甚至还有工作代码吗?记住,"如果它不起作用,不管它有多快不起作用。"(Mich Ravera)http://www.codingninja.co.uk/best programmers quotes/。

    你不知道瓶颈会在哪里,你已经专注于字典了。如果问题出在别的地方呢?

  • 你怎么知道字典类是如何实现的?可能它已经使用了一个带有哈希键的数组!
  • 另外,它实际上是".net dictionaries",而不是"c dictionaries",因为c只是使用框架的几种编程语言之一。


    Hello, I will be creating a project
    that will use dictionary lookups and
    inserts quite a bit. Is this something
    to be concerned about?

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

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

    Also, if I do benchmarking and such
    and it is really bad, then what is the
    best way of replacing dictionary with
    something else?

    最好的方法是建立一个合理的抽象层。如果您有一个表示"insert"和"lookup"抽象数据类型的类(或接口),那么您可以在不更改任何调用方的情况下替换其内部结构。

    注意,添加一个抽象层本身就有一个性能成本。如果您的分析显示抽象层太昂贵,那么如果每次调用额外的几纳秒太多,那么您可能必须除去抽象层。同样,这个决定将由实际的性能数据驱动。

    Would using an array with"hashed"
    keys even be faster? That wouldn't
    help on insert time though will it?

    无论你还是任何一个读过这篇文章的人,都不可能知道哪一篇文章写得更快,除非你用两种方式来写,然后在现实条件下用两种方式来衡量它。在"实验室"条件下进行这项工作会扭曲结果;当GC处于实际内存压力下时,您需要了解事情是如何工作的,等等。你不妨问一下,在明年的肯塔基德比中,哪匹马跑得更快。如果我们只通过看赛马表就知道答案,我们都已经很富有了。您不可能期望任何人知道在未指定的条件下,两个完全假设的、未写的代码片段中的哪一个会更快!


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

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


    Dictionary类实际上是作为哈希表实现的,这使得查找非常快(接近于o(1))。有关更多信息,请参阅API文档。我怀疑您自己是否能够更好地实现。


    我将对字典、hashtable(在.net中使用hashset)和本地类进行基准测试,看看在您的典型使用条件下哪一个最有效。

    通常我会说这很好(在这里插入StackOverflow最喜欢的早泄引用),但如果这是应用程序、基准、基准的核心部分。


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

    Also, if I do benchmarking and such
    and it is really bad, then what is the
    best way of replacing dictionary with
    something else?

    为此,尽可能将变量声明为IDictionary。这是字典派生的主要接口。(我假设,如果您非常关心性能,那么就不考虑非泛型集合。)然后,将来,您可以更改基础实现类,而不必更改任何使用该字典的代码。例如:

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


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

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

    如果您的字典有任何性能问题,那么很容易为任何类型的存储创建一个包装器,它具有与字典相同的方法和行为,这样您就可以无缝地替换它。


    如果您的应用程序是多线程的,那么性能的关键部分就是正确地同步这个字典。

    如果它是单线程的,那么几乎可以肯定瓶颈会出现在其他地方。比如从你读这些东西的地方读它们。


    我为UDP中继服务器使用字典。每次数据包到达时,它都执行dictionary.containskey和dictionary[key],并且工作得很好(大量客户机)。我做这件事的时候有点担心,但事实证明这是我最不应该担心的事情。


    看看C混合字典的用法

    HybridDictionary类

    This class is recommended for cases
    where the number of elements in a
    dictionary is unknown. It takes
    advantage of the improved performance
    of a ListDictionary with small
    collections, and offers the
    flexibility of switching to a
    Hashtable which handles larger
    collections better than ListDictionary


    您可以考虑使用c5库。我发现它设计得很快,很有思想。StackOverflow上的其他人也发现了同样的情况。使用c5,您可以选择使用通用类型的接口(带大写字母I),或者直接使用下面的数据结构。当然,接口允许您交换不同的实现,但我在性能测试中发现,这些接口会让您付出代价。


    您可能需要查看System.ObjectModel中的keyedcollection类。在msdn描述中,"为其键嵌入到值中的集合提供抽象基类。"