【问题标题】:Weird performance results using Dictionary<>使用 Dictionary<> 的奇怪性能结果
【发布时间】:2011-08-25 14:17:50
【问题描述】:

字典的性能似乎受到所存储项目大小的影响(这看起来很奇怪)。

这是我的简单课程:

public class MyObject
{
    public Guid Key { get; set; }
}

还有两个简单的测试:

private long _Iterations = 1000000;

[TestMethod]
public void ShouldTestDefaultConstructorPerformance()
{
    for (var i = 0; i < _Iterations; i++)
    {
        var obj = new MyObject() { Key = Guid.NewGuid() };
    }
}

[TestMethod]
public void ShouldTestDefaultGuidDictionaryPerformance()
{
    var dict = new Dictionary<Guid, MyObject>();
    for (var i = 0; i < _Iterations; i++)
    {
        var obj = new MyObject() { Key = Guid.NewGuid() };
        dict.Add(obj.Key, obj);
    }
}

最初我得到以下时间:

ShouldTestDefaultConstructorPerformance    : 00:00:00.580
ShouldTestDefaultGuidDictionaryPerformance : 00:00:01.238

现在,我将更改 MyObject 类:

public class MyObject
{
    public Guid Key { get; set; }

    private Dictionary<string, string> _Property0 = new Dictionary<string, string>();
    private Dictionary<string, string> _Property1 = new Dictionary<string, string>();
    private Dictionary<string, string> _Property2 = new Dictionary<string, string>();
    private Dictionary<string, string> _Property3 = new Dictionary<string, string>();
    private Dictionary<string, string> _Property4 = new Dictionary<string, string>();
    private Dictionary<string, string> _Property5 = new Dictionary<string, string>();
    private Dictionary<string, string> _Property6 = new Dictionary<string, string>();
    private Dictionary<string, string> _Property7 = new Dictionary<string, string>();
    private Dictionary<string, string> _Property8 = new Dictionary<string, string>();
    private Dictionary<string, string> _Property9 = new Dictionary<string, string>();
}

然后再次运行测试:

ShouldTestDefaultConstructorPerformance    : 00:00:01.333
ShouldTestDefaultGuidDictionaryPerformance : 00:00:07.556

在第二个测试中,对象构造的时间延长了 1.72 倍,但添加到字典需要 6.11 倍的时间。我预计测试需要更长的时间,但为什么字典需要 so 更长的时间来添加更大的对象?

【问题讨论】:

  • 这会测试对象的创建以及插入到字典中。您还没有将一个与另一个隔离开来。
  • 不完全是一个公平的比较,因为在第二个测试中,您分配了iterations*&lt;object size&gt;,而在第一种情况下(取决于运行时引擎和优化),您正在重用相同的内存空间。更好的性能比较是测试一的对象数组,测试二的字典......我想你会发现性能更接近。

标签: c# performance dictionary


【解决方案1】:

我认为人们需要更仔细地阅读问题,而不是急于发布答案。如果您仔细查看他的示例代码(两个测试),拥有一个带有 Guid 的 MyObject 和带有一个 Guid 和 10 个 Dict 的 MyObject 之间的区别在于他的循环不到一秒钟(对象构造)。但是添加字典至少要多花 5 秒。

【讨论】:

    【解决方案2】:

    我想我的答案是:使用分析器并找出哪个位实际上需要更长的时间

    这可能会突出实例化。也许:)

    【讨论】:

    • 是的。通过 SlimTune 跑进来,这表明 ctor 花费的时间最长。今日教训:不要总是相信 VS IDE 中显示的持续时间数据!非常感谢。
    • 下次我做同样的事情时,我会回来提醒自己这一点:)
    【解决方案3】:

    我认为var obj = new MyObject() { Key = Guid.NewGuid() }; 这一行实际上需要更长的时间,而不是字典中的Add()。你有没有在提供的inside方法中进行测量?

    【讨论】:

      【解决方案4】:

      您添加到字典中的每个对象都被赋予一个特殊的唯一标识符,以加快其在内存中的搜索和检索。这个特殊的唯一标识符(称为哈希)是通过分析对象的全部内容来计算的。对象越大,计算哈希的速度就越慢。

      如果您对它的工作原理感兴趣,请查看大学课程中的这个示例:http://www.ccs.neu.edu/home/sbratus/com1101/hash-dict.html

      【讨论】:

      • 我以为只有 Key 被散列了(因为这是 Dictionay 用来计算它在内部使用哪个存储桶的方法)?
      • -1 对象没有被赋予添加到字典的唯一标识符。哈希值不是唯一的。对象“大小”不会直接影响哈希计算速度。做功课
      • @Vijay 在您的情况下, Key 对哈希值计算没有贡献。您必须覆盖 GetHashCode 才能正常运行。
      • 因为 MyObject 是一个不正确的类:stackoverflow.com/questions/720177/…
      • @Brian 可以编写绿色测试,仅此而已。不覆盖 GetHashCode 函数,您正在破坏基于哈希的集合的合同。由于存在性能问题,还值得一提的是,基于哈希的插入和查找的算法时间也被破坏了
      猜你喜欢
      • 1970-01-01
      • 2019-04-22
      • 1970-01-01
      • 1970-01-01
      • 2012-04-09
      • 2010-09-14
      • 2011-12-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多