2012-10-07 4 views
15

PropertyInfo 속성을 가져 오는 데 너무 느린 이유는 무엇입니까? Reflection.Emit을 사용하여 대리인을 만들면 훨씬 빠릅니다.PropertyInfo SetValue 및 GetValue의 속도가 느린 이유는 무엇입니까?

그들은 뭔가 중요한 일을하고있어서 그들이 취하는 시간을 정당화 할 수 있습니까? 그게 ... Reflection.Emit을 사용하여 뭔가를 놓치고 있습니까 (개발 속도를 제외하고) PropertyInfo의 GetValueSetValue을 사용하는 대신 대리인을 만드시겠습니까?

추신 : 추측뿐만 아니라 증거를 제공해주세요!

+3

참고로, 당신은 PropertyInfo.GetGetMethod/PropertyInfo.GetSetMethod 그냥 Delegate.CreateDelegate 수 (물론 대리인을 캐시). – Ani

+0

위임자의 개체 인스턴스를 잠 가야합니다. 'GetValue'와'SetValue' 메소드는 호출 할 때 객체 인스턴스를 취합니다. –

+0

Delegate.CreateDelegate는 열기 및 닫기 인스턴스 대리자 개체를 만들 수 있습니다. – Ani

답변

16

(런타임 유형에 대한 PropertyInfo의 구상 서브 클래스) RuntimePropertyInfo의 구현은 생성 된 대리인이 아마 직접 메소드를 호출하는 반면, 반사 (MethodInfo.Invoke)를 통해 getter 및 setter 메소드를 호출하여 GetValueSetValue을 구현합니다. 따라서 질문은 다음과 같이 요약됩니다. RuntimeMethodInfo.Invoke은 컴파일 된 호출과 비교할 때 왜 느려 집니까?

  • 가 일관성 검사 (수와 유형을 수행 : Invoke이 작업을 많이 수행하기 때문에

    당신은 디 컴파일 (또는에 대한 참고 자료를 보면) RuntimeMethodInfo.Invoke 때이 아마 것을 볼 수 있습니다 전달 된 매개 변수가 서명과 일치합니까? 인스턴스가 전달 된 유형이 선언 유형과 일치합니까? 메서드가 정적이지만 전달 된 인스턴스였습니까?)

  • 가시성을 수행하고 (가시성 검사를 우회하는 경우) 보안 검사
  • 언랩 매개 변수 배열, ref pa 치료하기 나중에 다시 쓸 수 있도록 특별한 방법으로 rameters,
  • RuntimeMethodHandle과 관련된 런타임 유형 핸들과 메소드 핸들을 기반으로 메소드 포인터를 찾은 다음 호출해야합니다 메소드
  • 필요한 경우 반환 값을 상자에 넣고
  • 상자에 입력하고 모든 ref/out 매개 변수를 매개 변수 배열에 넣습니다.

런타임은 델리게이트를 실행 가능한 원시 코드로 컴파일 할 때 비슷한 일관성, 보안 및 가시성 검사를 수행합니다. 또한 boxing/unboxing 등을위한 코드를 내 보낸다. 그러나 이런 일을 한 번 수행하면 코드가 안전하게 실행될 수있다. 이것에 의해, 실제의 메소드 호출이 매우 싸게 동작합니다 (파라미터를로드 해 메소드 주소에 점프합니다). 반면

RuntimeMethodInfo.Invoke에 대한 모든 호출은 (따라서 GetValue/SetValue가) 컨텍스트 이후, 모든 일을 반복 할 필요가 - 매개 변수, 인스턴스 및 반환 형식의 사용 - 알려져 있지 않다. 그리고 이것은 아마도 너무 느린 이유 일 것입니다.

누락 된 부분 : 자신의 속성 호출 대리자를 내 보내면 당연히 boxing/unboxing, ref/out 매개 변수 등을 처리해야합니다.

10

방출을 사용할 필요가 없습니다. Expression을 사용하는 것이 훨씬 쉽습니다. SO에 설명 된대로 액세스 속도를 높일 수 있습니다. 헬퍼 클래스는 getter 또는 setter에 "메서드 포인터"(Action/Func)를 만듭니다. Action/Func을 재사용하면 일반 설정자만큼 빠르게 수행 할 수 있습니다. 당신이 Reflection.Emit를보다 성능 향상을 얻는 쉬운 방법을 찾고 있다면

// creating setter (once) 
    var propertyInfo = typeof(T).GetProperty(field); 
    var setter = FastInvoke.BuildUntypedSetter<T>(propertyInfo)); 

    // usage somehow later in a loop of data 
    foreach(var myobject in MySource) 
    { 
    setter(myobject, myValue) 
    } 
+0

http://stackoverflow.com/questions/1027980/improving-performance-reflection-what-alternatives-should-i-consider –

+0

@ sky-dev : 귀하의 요점은 무엇입니까? – Fried

+0

@Fried 당신의 링크가 깨졌지만 sky-devs 링크가 작동합니다. 나는 그의 요점 thats다고 생각한다. – ViRuSTriNiTy