A faster replacement to the Dictionary<TKey, TValue>
我需要一个快速更换的
- 泛型
- 添加
- 得到
- 包含
…就是这样。我不需要Linq的任何支持。而且应该很快。
一个简单的代码,比如:
1 2 3 4 5 6 7 | Stopwatch stopWatch = Stopwatch.StartNew(); Dictionary<string, string> dictionary = new Dictionary<string, string>(); dictionary.Add("fieldName","fieldValue"); dictionary.Add("Title","fieldVaaaaaaaaaaaaaaaaalue"); Console.WriteLine(stopWatch.Elapsed); |
…打印00:00:00.0001274,这对我来说是很长的时间,因为我的应用程序正在做许多其他的事情,其中一些是来自旧的慢库,我必须使用它们,并且不依赖于我。
关于如何实现更快的方法有什么想法吗?
谢谢您。
很可能您看到了JIT编译。在我的盒子上,我看到:
1 2 | 00:00:00.0000360 00:00:00.0000060 |
当我在同一进程中快速连续运行它两次时——而不是在调试器中。(确保您没有在调试器中运行它,或者它是一个无意义的测试。)
现在,测量任何微小的时间通常都是一个坏主意。您需要重复数百万次才能更好地了解它需要多长时间。
你有充分的理由相信它实际上会减慢你的代码——或者你是基于你最初的时间安排?
我怀疑你会发现比
编辑:我刚把一百万个元素添加到一个
考虑到你已经说过你在应用程序的其他地方使用了一些"老的慢库",这真的可能成为你的瓶颈吗?请记住,其他库的速度越慢,改进的集合类所带来的影响就越小。如果字典的更改只占您整个应用程序时间的1%,那么即使我们可以提供即时字典,您也只能将应用程序的速度提高1%。
像往常一样,找一个剖析器-它会让你更好地了解你的时间去哪里。
我同意乔恩斯基特的假设,这是最有可能的JIT编译。
也就是说,我想在这里添加一些其他信息:
大多数与使用
与字典实例相关的速度问题几乎总是哈希代码实现问题。如果在使用
为了从字典中获得良好的性能,
如果你做得对,我想你会非常满意默认的字典实现。
别忘了,您也在为该代码中的字典构造函数计时。我做了一个测试,将对构造函数的调用移出度量,并循环了10次。这是我的测试代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 | for (int i = 0; i < 10; i++) { Dictionary<string, string> test = new Dictionary<string, string>(); System.Diagnostics.Stopwatch watch = System.Diagnostics.Stopwatch.StartNew(); test.Add("fieldName","fieldValue"); test.Add("Title","fieldavlkajlkdjflkjalkjslkdjfiajwelkrjelrkjavoijl"); Console.WriteLine(watch.Elapsed); } Console.ReadKey(); |
结果如下:
2我不知道你能跑多快…
更新
看起来这也反映了乔恩·斯基茨的成绩……吉特。
如果您真的需要更好的性能,那么您将不得不放弃一些主要的功能,比如泛型、动态内存分配等。所有这些功能都会牺牲一些性能。
如果可能的话,我会尽量避免使用contains,并查看TryGetValue等。
使用ints作为键以获得最佳性能:
对于任何从谷歌来到这里的人,如果你想从字典中榨取最后一点性能,那么就用ints作为键。下面是比较int和string键的基准:https://jacksondunstan.com/articles/2527
这篇文章的作者甚至提到,如果您有这样的需求,将字符串转换为整数是值得的。
另外,请注意,在其他一些语言(如PHP)中也会发生同样的行为。事实上,php关联数组是字典,如果在php7中按升序使用int,它们的性能会大大优于字符串键。
你计划在字典中添加多少项?尽管Dictionary/Hashtable通常是最快的,但根据您所做的工作,可能有比Hashtable(字典中的底层结构)更快的东西(亦称为更适合)。根据用法,如果与某种跳过列表或甚至自平衡树或尝试组合,排序列表可能更快。尤其是如果您希望返回一个值范围而不是单个值。
在以下情况下,哈希表非常适合:
例如,如果要进行一些压缩,RB树比哈希表更好。
来源:http://en.wikipedia.org/wiki/hashtable动态调整大小
可以使用一个列表并定义一个枚举,例如fieldname=0,title=1,然后使用每个属性的唯一索引作为列表中的查找索引吗?这将是最快的解决方案,尽管这是自绑定到枚举以来最不灵活的解决方案。
很可能你找不到比字典快得多的东西。我只会用字典。然后,当你看到你没有达到你的性能目标时,一个分析器指出从字典中添加/删除是你的瓶颈,你可以考虑用一个更有针对性的类来替换。
请注意,如果不使用linq due等特性,则不会造成任何性能损失。