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


210

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

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


이 질문을 확인하고 싶을 수도 있습니다. stackoverflow.com/questions/224232/…
smaclell

1
fasterflect.codeplex.com에서 API를 사용하십시오. getters / setters / invokers와 다른 것들에 대해 500 배 정도 반사 속도를 높입니다. 확장해야 할 경우 작동 방식에 대한 소스 및 정보도 있습니다.
Brandon Moore

3
이 정보는 2014 년에 어떻게 확인합니까? 이 4 년 동안 무엇이 바뀌 었습니까?
Arnthor

1
인스턴스 속성에 값을 할당하는 간단한 작업은 간단한 코딩 (instance.property = value)보다 리플렉션 (PropertyInfo.SetValue (instance, value))보다 약 150 배 느립니다. 이것은 .NET 4.0에 있습니다.
Thanasis Ioannidis

답변:


130

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

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

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

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


try-catch에 오류를 기록하기 위해 리플렉션을 사용하여 메서드, 현재 메서드의 클래스 이름을 가져 왔습니다. 기본적으로 오류를 기록하는 동안 함수 이름을 하드 코딩하지 않도록합니다. 걱정해야합니까?
Sangram Nandkhile

@Sangram nope, 괜찮습니다
Karthik AMR

@Sangram 아니오, 끊임없이 잡기 위해 많은 오류가 발생하지 않는 한 다른 문제가 될 것입니다 :)
Martin Marconcini

5
@Sangram 리플렉션 성능은 귀하의 경우에는 문제가되지 않지만, 기존의 예외가 제공하는 것을 훨씬 더 우아한 방식으로 다시 구현하려고하는 것처럼 보입니다 ...
Jacek Gorgoń

152

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

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


18
Devscovery에도 참석했으며 .NET 3.5의 결과와 일치합니다. .NET 4 용 Devscovery 성능 벤치 마크 프로그램을 다시 컴파일하면 크게 개선되었습니다! 비용이 100 배 느려집니다. typeof () 조회에 리플렉션을 사용하는 것은 .NET 3.5와 .NET 4 사이에서 변경되지 않습니다.
John Wigger

61

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

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

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

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

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


9
반드시 그런 것은 아닙니다. DAL 변환은 수 천 항목에만 가능하지만 동시 사용자가 응용 프로그램 (웹인 경우)을 사용하여 곱하면 백만 개의 항목을 변환하는 것처럼 더해질 수 있습니다. 특정 방법이 100 배 느리면 작고 큰 세트에서는 그 속도가 훨씬 느려집니다. 느리게 느립니다.
Robert Koritnik

@RobertKoritnik 서버의 웹 메소드가 비동기식이 아니라고 가정합니다
Kurren

@kurren 비동기 성은 리플렉션에 영향을 미치지 않고 서버 리소스에 영향을 미칩니다. 비동기 웹 메서드는 물론 더 많은 사용자에게 서비스를 제공 할 수 있지만 리플렉션 속도는 여전히 느립니다. 그리고 자체적으로 반영 AFAIK는 어쨌든 동기 프로세스입니다. 반면에 데이터 가져 오기는 비동기 디자인에서 잘 작동하는 유일한 부분이 될 것입니다.
Robert Koritnik

3
차트에서 하이퍼 방법은 무엇입니까? 반사기와 다른 점은 무엇입니까?
Bryan Legend



12

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

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

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


Visual Studio에서 이와 같이 뛰어난 템플릿 지원을 고려하면 코드 생성을 사용하는 실용적인 방법입니다.
Sebastian

12

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

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


5
나에게 새로운 단어를 가르쳐 준 +1 : anathema. 또한 비이성적 인 두려움에 대한 언급. 나는 불합리하게 두려워하는 프로그래머를 두려워합니다. 실제로 그들이하는 일을 알지 못하고 다른 사람들이 말하는 것에 기초하여 행동합니다. 기침화물 숭배 기침
bsneeze

1
아아 카고 컬트 이제 호기심 많은 인간 행동의 좋은 예가 있습니다.
Quibblesome

10

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

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

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


13
공정하게 말하자면, 반사 형 검사가 빠릅니다.
Jimmy

1
이러한 '성능이 중요한 코드'의 경우 실제로 .NET을 사용해야합니까?
Seph

1
@Seph : .NET의 동적 / 반사 부분 그러나 일반적인 C # /. NET은 왜 안됩니까? C ++ 대 C # 속도 향상은 응용 프로그램 계층에서 거의 없습니다 (C ++는 집중적 인 수학 루틴에서 여전히 몇 % 빠릅니다). 그리고 당신은 어셈블리를 제안하지 않는 것 같아요 ...
DeepSpace101

박스형 값 유형 (예 : 객체)을 잠글 수 있습니다. @BryceWagner가 정확합니다.
Fowl

1
공정하게 (나에게) 대답은 "일반적인 말도 안되는 것"보다는 "더 이상 쓸모 없다"고 말하는 것이 더 정확합니다. lock (obj)의 동작에 대한 나의 언급은 작성된 시점에 정확했지만 CLR의 구현 별 동작은 오랫동안 사라졌습니다.
McKenzieG1

5

프로그래밍의 모든 것과 마찬가지로 성능 비용과 이익을 균형있게 유지해야합니다. 리플렉션은주의해서 사용할 때 매우 유용한 도구입니다. 리플렉션을 사용하여 바인딩을 수행하는 C #에서 O / R 매핑 라이브러리를 만들었습니다. 이것은 환상적으로 잘 작동했습니다. 대부분의 리플렉션 코드는 한 번만 실행되었으므로 성능 저하는 거의 없었지만 이점은 컸습니다. 새로운 부채꼴 정렬 알고리즘을 작성하는 경우 아마도 크기가 제대로 조정되지 않기 때문에 리플렉션을 사용하지 않을 것입니다.

귀하의 질문에 정확하게 답변하지 않은 것에 대해 감사드립니다. 내 요점은 실제로 중요하지 않다는 것입니다. 적절한 곳에 반사를 사용하십시오. 사용 방법과시기를 배우는 데 필요한 또 다른 언어 기능 일뿐입니다.


3

리플렉션은 오브젝트를 자주 생성하는 데 사용하면 성능에 현저한 영향을 줄 수 있습니다. Composite UI Application Block을 기반으로 응용 프로그램을 개발했습니다.리플렉션에 크게 의존하는 을 . 리플렉션을 통한 객체 생성과 관련하여 눈에 띄는 성능 저하가있었습니다.

그러나 대부분의 경우 리플렉션 사용에는 문제가 없습니다. 일부 어셈블리를 검사 해야하는 경우 매우 가볍고 빠른 Mono.Cecil 을 권장합니다.


3

반영은 매개 변수 목록과 일치하는 메소드를 요청할 때마다 런타임에서 수행해야하는 많은 검사로 인해 비용이 많이 듭니다. 내부 어딘가에 코드의 유형에 대한 모든 메소드를 반복하고, 가시성을 확인하고, 리턴 유형을 확인하고, 각 매개 변수의 유형을 확인합니다. 이 모든 것은 시간이 걸립니다.

해당 메소드를 내부적으로 실행할 때 실제 대상 메소드를 실행하기 전에 호환 가능한 매개 변수 목록을 전달했는지 확인하는 것과 같은 일부 코드가 있습니다.

가능하면 나중에 계속해서 재사용 할 경우 메소드 핸들을 캐시하는 것이 좋습니다. 모든 좋은 프로그래밍 팁과 마찬가지로 자주 반복하지 않는 것이 좋습니다. 이 경우 지속적으로 특정 매개 변수를 사용하여 메서드를 조회 한 다음 매번 실행하는 것이 낭비입니다.

소스를 둘러보고 수행중인 작업을 살펴보십시오.


3

모든 것과 마찬가지로 상황을 평가하는 것이 전부입니다. 에서 DotNetNuke의 라는 매우 핵심 구성 요소가있다FillObject 사용하는 반사가 데이터 행에서 오브젝트를 채우는 것으로는.

이것은 매우 일반적인 시나리오이며 MSDN에 대한 리플렉션을 사용하여 비즈니스 개체를 ASP.NET 폼 컨트롤에 바인딩 하는 기사가 있습니다. 에서 성능 문제를 다루는 있습니다.

성능을 제외하고는 특정 시나리오에서 리플렉션을 사용하는 것이 마음에 들지 않는 한 가지 점은 코드를 한눈에 이해할 수있는 능력을 줄이는 경향이 있다는 것입니다. LINQ to SQL 과 같은 강력한 형식의 데이터 세트와 달리 시간 안전성 .


2

리플렉션은 앱 성능을 크게 저하시키지 않습니다. 리플렉션을 사용하지 않으면 서 특정 작업을 더 빨리 수행 할 수 있지만 리플렉션이 일부 기능을 달성하는 가장 쉬운 방법이라면 사용하십시오. 퍼포먼스 문제가된다면 리플렉션에서 코드를 리팩터링 할 수 있습니다.


1

나는 당신이 그 답이 달려 있다는 것을 알게 될 것이라고 생각합니다. 작업 목록 응용 프로그램에 넣고 싶다면 큰 문제가 아닙니다. Facebook의 퍼시스턴스 라이브러리에 넣으려면 큰 문제입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.