1

我有一个高级程序,它从数据库中检索数据并通过 C# 中的 ExpandoObjects 从数据中创建对象。

我现在正在优化我的整个过程,但遇到了一段代码,这是性能方面的瓶颈。我很好奇我可以在多大程度上进一步优化这段代码,并且已经通过执行以下操作将其运行速度提高了 3 倍:

  • 在单独的 for 循环中分隔“查找“类型”部分”,并且仅在尚未初始化时对其进行迭代。
  • 添加了当值为 null 时创建一个空字符串的情况,因为由于某种原因 Dictionary.Add 在添加 Null 值时会减慢很多。

        // Holds all objects that are created inside the object.
        Dictionary<string, IDictionary<string, dynamic>> objects = new Dictionary<string, IDictionary<string, dynamic>>();
    
        // This foreach loop is the slowest part!
        foreach (KeyValuePair<string, dynamic> pair in fields)
        {
            string type = pair.Key.Split('_')[0];
    
            IDictionary<string, dynamic> obj;
            if (!objects.TryGetValue(type, out obj))
            {
                obj = new ExpandoObject();
                objects.Add(type, obj);
            }
            int location = pair.Key.IndexOf(type + "_");
            string key = pair.Key.Remove(location, type.Length + 1);
            if (pair.Value == null)         // If Value is null, replace it with an empty string (dictionary slows quite alot when passing it null values)
                obj.Add(key, "");
            else
                obj.Add(key, pair.Value);         
        }
    
        if (types == null)
            types = objects.Select(x => x.Key).ToList();
    

我想知道,在添加 Null 值时字典是如何减慢这么多的,是在底层结构中遇到空值时它会执行特殊操作吗?还有什么我缺少进一步优化代码的东西吗?

再次非常感谢任何帮助。


更新

  • 使用我从 SO 收集的最新更改编辑了代码。
4

1 回答 1

2

TryGetValue您可以通过使用而不是避免在字典中进行多次查找ContainsKey

foreach (KeyValuePair<string, dynamic> pair in fields) 
{ 
    string type = pair.Key.Split('_')[0]; 

    IDictionary<string, dynamic> obj;
    if (!objects.TryGetValue(type, out obj)) 
    { 
        obj = new ExpandoObject(); 
        objects.Add(type, obj); 
    } 
    int location = pair.Key.IndexOf(type + "_"); 
    string key = pair.Key.Remove(location, type.Length + 1); 
    if (pair.Value == null)
        obj.Add(key, ""); 
    else 
        obj.Add(key, pair.Value);            
} 

顺便说一句:我没有看到你types在第二个foreach循环中使用。因此,您可以用这个简单的代码替换第一个 foreach循环:

types = objects.Select(x => x.Key).ToList();

这应该可以节省大量时间,因为它消除了types列表中的缓慢搜索和类型的双重解析。

显然,这需要放在foreach我上面显示的循环之后。

于 2012-08-29T10:45:54.273 回答