我应该关注.NET字典的速度吗?
我将创建一个将使用字典查找和插入相当多的项目。 这是值得关注的吗?
此外,如果我进行基准测试等并且它真的很糟糕,那么用其他东西替换字典的最佳方法是什么? 使用带有“哈希”键的数组会更快吗? 那会对插入时间有所帮助吗?
此外,我不认为我是微优化的,因为这确实是生产服务器上代码的重要组成部分,因此如果需要额外的100毫秒才能完成,那么我们将寻找新的方法来处理这个问题。
-
你是微观优化。 你甚至还有工作代码吗? 请记住,“如果它不起作用,它无效的速度无关紧要。” (Mich Ravera) http://www.codingninja.co.uk/best-programmers-quotes/ 。
你不知道瓶颈会在哪里,而且你已经专注于词典。 如果问题出在其他地方怎么办?
- 你怎么知道Dictionary类是如何实现的? 也许它已经使用了带有散列键的数组!
PS它实际上是“.NET Dictionaries”,而不是“C#Dictionaries”,因为C#只是使用该框架的几种编程语言之一。
您好,我将创建一个将使用字典查找和插入相当多的项目。 这是值得关注的吗?
是。 预先考虑性能因素总是明智的。
您需要考虑的forms如下:您的关注应该是鼓励您编写切合实际的,以用户为中心的性能规范。 它应该鼓励您尽早开始编写性能测试并经常运行它们,这样您就可以看到产品的每一次更改如何影响性能。 这样,当代码更改导致影响用户的性能变化时,您将立即得到通知。 它应该鼓励你经常运行配置文件,这样你就可以根据经验测量推断性能,而不是随机猜测和预测。
此外,如果我进行基准测试等并且它真的很糟糕,那么用其他东西替换字典的最佳方法是什么?
最好的方法是构建一个合理的抽象层。 如果您有一个表示“插入”和“查找”抽象数据类型的类(或接口),则可以在不更改任何调用者的情况下替换其内部。
请注意,添加抽象层本身会产生性能成本。 如果您的分析显示抽象层太昂贵,如果每次调用额外的几纳秒太多,那么您可能不得不摆脱抽象层。 同样,这个决定将由现实世界的性能数据驱动。
使用带有“哈希”键的数组会更快吗? 那会对插入时间有所帮助吗?
无论是你还是读过这篇文章的人都不可能知道哪一个更快,直到你用两种方式写它,然后在真实条件下以两种方式对它进行基准测试。 在“实验室”条件下进行此操作会使您的结果出现偏差; 当GC处于实际内存压力下时,您需要了解其工作原理,等等。 你不妨问我们明年的肯塔基赛马会哪匹马跑得更快。 如果我们只是通过观察比赛forms就知道了答案,那么我们都已经变得富有了。 在未指定的条件下,你不可能指望任何人知道两个完全假设的,不成文的代码中的哪一个会更快!
等一下,看看你的应用程序的性能是否低于预期
如果是,则使用分析器确定字典查找是否是问题的根源
如果是,那么用代表性数据进行一些测试,以查看列表的另一个选择是否更快。
简而言之 – 不 ,一般来说,在遇到问题之前,您不应该担心实现细节的性能。
Dictionary
类实际上是作为哈希表实现的,它使查找非常快(接近O(1))。 有关更多信息,请参阅API文档 。 我怀疑你自己可以做出更好的实施。
我会做一下Dictionary的基准测试,HashTable(.NET中的HashSet),也许是一个本土的类,看看哪些在你的典型使用条件下效果最好。
通常我会说这很好(插入StackOverflow最喜欢的早泄引用), 但如果这是应用程序的核心,Benchmark,Benchmark,Benchmark。
我能想到的唯一问题是字典的速度依赖于具有相当快的GetHashCode方法的密钥类。 查找和插入非常快,所以你不应该有任何问题。
关于使用数组,这就是Dictionary类已经做的。 实际上它使用两个数组,一个用于键,一个用于值。
如果您对Dictionary有任何性能问题,那么为任何类型的存储创建包装都会非常容易,它具有与Dictionary相同的方法和行为,因此您可以无缝地替换它。
我不确定是否还有人真正回答过这一部分:
此外,如果我进行基准测试等并且它真的很糟糕,那么用其他东西替换字典的最佳方法是什么?
为此,尽可能将变量声明为IDictionary
。 这是Dictionary派生的主要接口。 (我假设如果你非常关心性能,那么你不会考虑非generics集合。)然后,在将来,您可以更改底层实现类,而无需更改任何使用该代码的代码。字典。 例如:
IDictionary myDict = new Dictionary();
如果你的应用程序是multithreading的,那么性能的关键部分就是正确地同步这个字典。
如果它是单线程的,那么几乎肯定会出现其他地方的瓶颈。 比如从你阅读它们的任何地方读取这些对象。
看看C#HybridDictionary用法
HybridDictionary类
对于字典中元素数量未知的情况,建议使用此类。 它利用了具有小集合的ListDictionary的改进性能,并提供了切换到Hashtable的灵活性,Hashtable比ListDictionary更好地处理更大的集合
我使用Dictionary for UDP relay server。 每次数据包到达时,它执行Dictionary.ContainsKey和Dictionary [Key],它工作得很好(大量的客户端)。 当我制作东西时我有些担心,但事实certificate这是我应该担心的最后一件事。
您可以考虑使用C5库。 我发现它非常快速且经过精心设计。 stackoverflow上的其他人也发现了相同的结果。 使用C5,您可以选择使用通用类型接口(带有captial I),或直接使用下面的数据结构。 当然,接口允许您交换不同的实现,但我在性能测试中发现接口将花费您。
您可能希望查看System.ObjectModel中的KeyedCollection类。 从MSDN描述中,“为其键嵌入值的集合提供抽象基类”。