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 値を追加すると、ディクショナリの速度が低下するのはなぜですか。基になる構造で、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ところで:その2番目のforeachループで使用しているとは思いません。したがって、最初の foreachループを次の単純なコードに置き換えることができます。

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

typesこれにより、リスト内の遅い検索と型の二重解析がなくなるため、かなりの時間を節約できます。

foreach明らかに、これは上で示したループの後に配置する必要があります。

于 2012-08-29T10:45:54.273 に答える