[C#] .NET 리플렉션 비용이 얼마나 듭니까?

나는 반사가 얼마나 나쁜지를 끊임없이 듣는다. 나는 일반적으로 성찰을 피하고 문제가 없으면 내 문제를 해결할 수없는 상황을 거의 찾지 않지만 궁금한 점은 …

응용 프로그램에서 리플렉션을 사용한 사용자의 경우 성능 적중을 측정 한 적이 있습니까?



답변

그것은. 그러나 그것은 당신이하려는 일에 달려 있습니다.

리플렉션을 사용하여 어셈블리 (플러그인)를 동적으로로드하고 성능 “불이익”은 문제가되지 않습니다. 작업은 응용 프로그램 시작 중에 수행하는 작업이기 때문입니다.

그러나 각각에 대해 리플렉션 호출을 사용하여 일련의 중첩 루프 내부에 반영하는 경우 코드를 다시 방문해야한다고 말하고 싶습니다. 🙂

“몇 시간”작업의 경우 리플렉션을 완벽하게 수용 할 수 있으며 지연이나 문제가 발생하지 않습니다. 매우 강력한 메커니즘이며 .NET에서도 사용되므로 시도하지 말아야 할 이유를 모르겠습니다.


답변

Jeff Richter는 자신의 강연 에서 일상적인 것들의 성능 (Performance of Everyday Things )을 통해 리플렉션을 통해 메서드를 호출하는 것이 일반적으로 호출하는 것보다 약 1000 배 느립니다 .

Jeff의 팁 : 메소드를 여러 번 호출해야하는 경우 리플렉션을 한 번 사용하여 찾은 다음 델리게이트에 할당 한 다음 델리게이트 를 호출하십시오.


답변

리플렉션 성능은 구현에 따라 다릅니다 (예 : 반복 호출을 캐시해야 함 entity.GetType().GetProperty("PropName")). 매일 보는 대부분의 리플렉션은 데이터 리더 또는 다른 리포지토리 유형 구조에서 엔터티를 채우는 데 사용되므로 개체 속성을 가져 오거나 설정할 때 리플렉션에 대한 성능을 구체적으로 벤치 마크하기로 결정했습니다.

반복되는 모든 호출을 캐시하고 실제 SetValue 또는 GetValue 호출의 시간 만 캐시하기 때문에 공정하다고 생각되는 테스트를 고안했습니다. 성능 테스트를위한 모든 소스 코드는 https://bitbucket.org/grenade/accessortest 에서 bitbucket에 있습니다 . 면밀히 검토하고 격려하십시오.

내가 얻은 결론은 반사 구현이 잘 수행 될 때 한 번에 100,000 행 미만을 반환하는 데이터 액세스 계층에서 반사를 제거하기 위해 실용적이지 않고 눈에 띄는 성능 개선을 제공하지 않는다는 것입니다.

채워진 엔터티 수에 대한 시간 (y) 그래프 (x)

위의 그래프는 저의 작은 벤치 마크의 결과를 보여 주며 반사를 능가하는 메커니즘은 100,000 사이클 마크 후에 만 ​​눈에 띄게 나타납니다. 대부분의 DAL은 한 번에 수백 또는 수천 행만 반환하며 이러한 수준에서는 반향이 잘 수행됩니다.


답변

루프가 아닌 경우 걱정하지 마십시오.


답변

저의 가장 적절한 경험은 큰 개체 모델에서 같은 유형의 두 데이터 엔터티를 속성별로 비교하는 코드를 작성하는 것이 었습니다. 제대로 작동하고 시도해 보았지만 개처럼 달렸습니다.

나는 낙담했지만 밤새 논리를 바꾸지 않고 동일한 알고리즘을 사용하여 비교를 수행하지만 속성에 정적으로 액세스하는 메소드를 자동 생성 할 수 있다는 것을 깨달았다. 이 목적을 위해 코드를 수정하는 데 시간이 전혀 걸리지 않았으며 객체 모델이 변경 될 때마다 버튼을 클릭하면 업데이트 될 수있는 정적 코드로 엔티티를 속성별로 비교할 수있는 능력이있었습니다.

내 요점 : 동료들과의 대화에서 여러 번 반영한 이후로 리플렉션을 사용하면 런타임 작업을 수행하는 대신 컴파일하기 위해 코드를 자동 생성하는 것이 가능하며 종종 고려할 가치가 있다고 지적했습니다.


답변

대규모가 아닙니다. Martin이 말했듯이 바보 같은 위치에서 사용하지 않는 한 데스크톱 개발에서 문제가 발생하지 않았습니다. 많은 사람들이 데스크톱 개발 성능에 대해 전혀 비이성적 인 두려움을 가지고 있다고 들었습니다.

에서 Compact Framework에서 (나는 보통에있어)하지만, 그것은 거의의 저주 대부분의 경우 전염병처럼 피해야한다. 나는 그것을 자주 사용하지 않고 도망 칠 수는 있지만 재미가 덜한 응용 프로그램에는 실제로주의해야합니다. 🙁


답변

성능에 중요한 코드를 위해 .NET 라이브러리에서 내부적으로 수행 한 리플렉션에 대해서도 걱정해야 할 정도로 나쁩니다.

다음 예제는 더 이상 사용되지 않습니다 (2008 년). 그러나 최근에는 최신 CLR 버전에서 수정되었습니다. 일반적으로 반사는 여전히 다소 비용이 많이 드는 것입니다!

적절한 예 : 고성능 코드의 lock (C #) / SyncLock (VB.NET) 문에서 “Object”로 선언 된 멤버를 사용해서는 안됩니다. 왜? CLR은 값 형식을 잠글 수 없으므로 런타임 리플렉션 형식 검사를 수행하여 Object가 실제로 참조 형식이 아닌 값 형식인지 확인해야합니다.