更快地替换Dictionary

我需要快速替换System.Collections.Generic.Dictionary 。 我的申请应该非常快。 所以,替换应该支持:

  • generics
  • 得到
  • 包含

……就是这样。 我不需要LINQ或任何东西的任何支持。 它应该很快

一个简单的代码如:

 Stopwatch stopWatch = Stopwatch.StartNew(); Dictionary dictionary = new Dictionary(); dictionary.Add("fieldName", "fieldValue"); dictionary.Add("Title", "fieldVaaaaaaaaaaaaaaaaalue"); Console.WriteLine(stopWatch.Elapsed); 

…打印00:00:00.0001274,这对我来说很多时间,因为我的应用程序正在做很多其他的事情,其中​​一些来自旧的慢速库我必须使用并且不依赖于我。

关于如何实施更快速的任何想法?

谢谢。

你有机会看到JIT编译。 在我的盒子上,我看到:

 00:00:00.0000360 00:00:00.0000060 

当我在同一个过程中快速连续运行两次 – 而不是在调试器中。 (确保你没有在调试器中运行它,否则这是一个毫无意义的测试。)

现在,在任何时候测量微小通常都是一个坏主意。 您需要迭代数百万次才能更好地了解它需要多长时间。

您是否有充分的理由相信它实际上会降低您的代码速度 – 或者您是基于原始时机进行的?

我怀疑你会发现比Dictionary更快的任何东西,我会惊讶地发现它是瓶颈。

编辑:我刚刚对Dictionary添加一百万个元素进行基准测试Dictionary其中所有键都是现有对象(数组中的字符串),重用相同的值(因为它不相关)并指定一个百万的容量建筑 – 我两岁的笔记本电脑花了大约0.15秒。

真的可能是你的瓶颈,因为你已经说过你在你的应用程序的其他地方使用了一些“旧的慢速库”吗? 请记住,其他库越慢,改进的集合类的影响就越小。 如果字典更改仅占您整个应用程序时间的1%,那么即使我们可以提供即时字典,您也只能将应用程序加速1%。

与以往一样,获取一个分析器 – 它会让您更好地了解您的时间。

我同意Jon Skeet的假设,即这很可能是JIT编译。

话虽这么说,我想在这里添加一些其他信息:

与使用Dictionary相关的大多数速度问题与Dictionary的实现无关。 Dictionary非常快,开箱即用。 打败它会很困难。

与Dictionary实例相关的速度问题几乎总是实际上是哈希代码实现问题。 如果您在使用Dictionary时遇到速度问题,请重新访问您在MyCustomClass上定义的GetHashCode()实现。 如果您使用自定义结构作为键,则这一点更为重要。

为了从Dictionary中获得良好的性能, GetHashCode()应该是:

  1. 快速
  2. 能够提供产生很少冲突的哈希码。 在可能的情况下,唯一实例应生成唯一的哈希值。

如果你做对了,我想你会对默认的Dictionary实现非常满意。

不要忘记,您也在该代码中对Dictionary构造函数进行计时。 我做了一个测试,将测量中的调用移到构造函数中,然后循环10次。 这是我的测试代码:

 for (int i = 0; i < 10; i++) { Dictionary test = new Dictionary(); System.Diagnostics.Stopwatch watch = System.Diagnostics.Stopwatch.StartNew(); test.Add("fieldName", "fieldValue"); test.Add("Title", "fieldavlkajlkdjflkjalkjslkdjfiajwelkrjelrkjavoijl"); Console.WriteLine(watch.Elapsed); } Console.ReadKey(); 

以下是结果:

 00:00:00.0000607 00:00:00.0000025 00:00:00.0000015 00:00:00.0000015 00:00:00.0000016 00:00:00.0000017 00:00:00.0000016 00:00:00.0000016 00:00:00.0000016 00:00:00.0000015 

我不确定你得到多快多少…

更新

看起来这也反映了Jon Skeets的结果… JIT。

如果你真的需要更好的性能,那么你将不得不放弃一些重要的东西 – 比如generics,动态内存分配等等。所有这些function都会牺牲一些性能。

如果可能的话我会避免使用Contains并查看TryGetValue等。

赔率是你找不到比Dictionary更快的东西。 我会用字典。 然后,当您发现自己没有达到性能目标时,并且分析器指示从词典中添加/删除是您的瓶颈,您可以考虑使用更具针对性的类替换。

请注意,如果不使用LINQ等function,则不会导致任何性能损失。

你可以使用List并定义一个枚举,例如,fieldName = 0,Title = 1并使用每个属性的唯一索引作为列表中的查找索引吗? 这将是最快的解决方案,虽然最不灵活,因为你被绑定到枚举。

您打算将多少项添加到词典中? 虽然Dictionary / Hashtable通常是最快的,但取决于你正在做什么,可能比Hashtable(字典中的底层结构)更快(也称为更适合)。 根据用法,如果与某种跳过列表甚至是自平衡树或尝试结合使用,SortedList可能会更快。 特别是如果您希望返回一系列值而不是单个值。

Hashtable非常适合以下情况:

  1. 您知道在表格开始之前您打算存储多少项目。 动态resize将非常痛苦!
  2. 你有一个很好的哈希算法和均匀分布,.NET就是这样做的
  3. .NET有一个很好的机制来解决冲突
  4. 您正在寻找单一价值
  5. 您可以保证所有值都是唯一的

例如,如果您正在进行一些压缩,则RB-Tree优于Hashtable。

资料来源: http : //en.wikipedia.org/wiki/Hashtable#Dynamic_resizing

以最大性能使用密钥作为密钥:

对于那些从谷歌来到这里的人来说,如果你想从词典中挤出最后一点性能,那就用Ints作为键。 这是比较Int与String Keys的基准: https : //jacksondunstan.com/articles/2527

该文章的作者甚至提到,如果你有这样的需要,将字符串转换为int是值得的。

另请注意,在PHP等其他语言中也会出现同样的行为。 Php关联数组 – 实际上是字典,如果你在PHP7 中按升序使用Ints,它们会大大优于字符串键。