C# 更快地替换词典<;TKey,TValue>;

C# 更快地替换词典<;TKey,TValue>;,c#,.net,performance,generics,dictionary,C#,.net,Performance,Generics,Dictionary,我需要快速更换系统.Collections.Generic.Dictionary。我的应用程序应该非常快速。因此,替换应支持: 仿制药 加 得到 包含 。。。就这样。我不需要LINQ的任何支持。而且它应该是快速的 一个简单的代码如下: Stopwatch stopWatch = Stopwatch.StartNew(); Dictionary<string, string> dictionary = new Dictionary<string, string>();

我需要快速更换
系统.Collections.Generic.Dictionary
。我的应用程序应该非常快速。因此,替换应支持:

  • 仿制药
  • 得到
  • 包含
。。。就这样。我不需要LINQ的任何支持。而且它应该是快速的

一个简单的代码如下:

Stopwatch stopWatch = Stopwatch.StartNew();

Dictionary<string, string> dictionary = new Dictionary<string, string>();
dictionary.Add("fieldName", "fieldValue");
dictionary.Add("Title", "fieldVaaaaaaaaaaaaaaaaalue");

Console.WriteLine(stopWatch.Elapsed);
Stopwatch Stopwatch=Stopwatch.StartNew();
字典=新字典();
添加(“字段名”、“字段值”);
添加(“标题”、“字段值”);
控制台写入线(秒表已过);
。。。打印00:00:00.0001274,这对我来说是一段很长的时间,因为我的应用程序正在做许多其他事情,其中一些来自我必须使用且不依赖于我的旧慢速库

有没有关于如何实施更快的方案的想法


谢谢。

您可能看到了JIT编译。在我的盒子上,我看到:

00:00:00.0000360
00:00:00.0000060
当我在同一进程中快速连续运行它两次时,而不是在调试器中。(确保您没有在调试器中运行它,否则这是一个无意义的测试。)

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

您是否有充分的理由相信它实际上会减慢您的代码速度?或者您是否完全基于您最初的计时

我怀疑你能找到比字典快得多的东西,我会非常惊讶地发现这是瓶颈

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

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

和以往一样,找一个分析器-它会让你更好地了解你的时间在哪里。

我同意的假设,这很可能是JIT编译

话虽如此,我想在此添加一些其他信息:

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

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

为了获得字典的良好性能,
GetHashCode()
应该是:

  • 快速
  • 能够提供产生少量冲突的哈希代码。唯一实例应尽可能生成唯一的哈希值

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

    如果你真的需要更好的性能,你将不得不放弃一些主要功能,比如泛型、动态内存分配等。所有这些功能都会牺牲一些性能


    如果可能的话,我会尽量避免使用Contains,并查看一下etc.

    很可能你找不到比字典更快的东西了。我只会用字典。然后,当你看到你没有达到你的PARF目标时,一个分析器指出从字典中添加/删除是你可以考虑用一个更有针对性的类来替换的瓶颈。
    请注意,如果不使用LINQ due等功能,它们不会导致任何性能损失。

    别忘了,在该代码中还对字典构造函数计时。我做了一个测试,将对构造函数的调用移出了度量,并循环了10次。以下是我的测试代码:

    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();
    
    我不知道你能比那快多少

    更新


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

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

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

    在以下情况下,哈希表非常适合:

  • 在开始填充表之前,您知道要存储多少项。动态调整大小将是非常痛苦的
  • 你有一个很好的散列算法,分布均匀,而.NET就是这样
  • 有一个很好的机制来解决冲突,而.NET就是这样做的
  • 您正在寻找单个值
  • 您可以保证所有值都是唯一的
  • 例如,如果您正在进行一些压缩,那么RB树比哈希表更好


    来源:

    使用INT作为键以获得最佳性能:

    对于任何从谷歌来到这里的人来说,如果你想榨取每一点性能的话
    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
    
    var dictionary = new Dictionary<string, string>(StringComparer.Ordinal); 
    
    (
          index =
              SomeKeyString [ 0 ] * 256 * 256 * 256
            + SomeKeyString [ 1 ] * 256 * 256
            + SomeKeyString [ 2 ] * 256
            + SomeKeyString [ 3 ] 
    )