2016-08-03 5 views
1

this question 오늘은 ConcurrentDictionary 메서드와 관련하여 약간의 성능 차이가 있음을 알았습니다. 조기 마이크로 최적화로 보았습니다.C# 람다 할당 및 수집

그러나 생각해 보면 (실수하지 않으면) 람다를 메서드에 전달할 때마다 CLR은 메모리를 할당하고 필요한 경우 적절한 클로저를 전달한 다음 수집해야합니다. 얼마 후. 조건 전에 확인 (같은

// this is definitely an allocation 
return concurrent_dict.GetOrAdd(key, k => ValueFactory(k, stuff)); 
  • 외부 검사 : 폐쇄없이

    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. 람다

      는 세 가지 가능성이 있습니다 자물쇠) :

      // 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과 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 구현 예의 익명 함수