2016-08-03 5 views
1

this question今日、ConcurrentDictionaryのメソッドに関するいくつかのパフォーマンスの違いがわかりました。私はこれを早期のマイクロ最適化と見ていました。C#ラムダの割り当てと収集

しかし、私が誤解していない場合、ラムダをメソッドに渡すたびに、CLRはメモリを割り当て、適切なクロージャを渡し(必要な場合)それはしばらくしてから。

三つの可能性があります:閉鎖せずに

  1. ラムダ:

    // the lambda should internally compile to a static method, 
    // but will CLR instantiate a new ManagedDelegate wrapper or 
    // something like that? 
    return concurrent_dict.GetOrAdd(key, k => ValueFactory(k)); 
    
  2. クロージャとラムダ:

    // this is definitely an allocation 
    return concurrent_dict.GetOrAdd(key, k => ValueFactory(k, stuff)); 
    
  3. チェックアウトサイド(前の状態をチェックすることなどがロック):

    // no lambdas in the hot path 
    if (!concurrent_dict.TryGetValue(key, out value)) 
        return concurrent_dict.GetOrAdd(key, k => ValueFactory(k)); 
    

第三の場合は明らかに割り当てフリーで、もう一つは割り当てが必要になります。

しかし、(より新しいCLRバージョンでは)完全に割り振りのない最初のケース(キャプチャを持たないラムダ)ですか?また、これはランタイムの実装の詳細なのか、それとも標準で指定されているものなのでしょうか?

答えて

1

まず第一に、CLRはラムダが何であるか分かりません。これはC#の概念です。コンパイルされています。 C#言語は、ラムダを記述した代理値を提供します。

C#では、デリゲートインスタンス(または基本となるメソッド)が共有されているとは限りません。実際、私は、共有ラムダ代理人の初期化はスレッドが安全でなく、レイシーであると考えています。したがって、タイミングに応じて、1つまたは複数のデリゲートインスタンスが表示されることがあります。

言語の実装の詳細です。

実際には、フォーム1とフォーム3を共有することができます。これはパフォーマンスにとって重要です。これが今の場合ではない場合、私はそれが優先度の高いバグと考えられると思います。

0

割り当てによって、生成されたDisplayClassを意味する場合は、最初のケースは割り当てなしになります。しかし、まだ割り当てが必要です。例えば、Func<Key, Value>です。

6.5.3実施例

public delegate void D(); 

匿名関数の最も簡単な形式には、外側の変数をキャプチャしないものである:これは、その参照するデリゲートのインスタンスに変換することができ

class Test 
{ 
    static void F() { 
     D d =() => { Console.WriteLine("test"); }; 
    } 
} 

匿名関数のコードが置かれたコンパイラ生成静的メソッド:

あなたはそれぞれのケースで起こって内容​​を確認したい場合は0、(静的\インスタンスフィールド、地元の人々、これ、生成された共有オブジェクト)

C# specificationを見て、セクション6.5.3実施例の匿名関数

関連する問題