나는 반사가 얼마나 나쁜지를 끊임없이 듣는다. 나는 일반적으로 성찰을 피하고 문제가 없으면 내 문제를 해결할 수없는 상황을 거의 찾지 않지만 궁금한 점은 ...
응용 프로그램에서 리플렉션을 사용한 사용자의 경우 성능 적중을 측정 한 적이 있습니까?
나는 반사가 얼마나 나쁜지를 끊임없이 듣는다. 나는 일반적으로 성찰을 피하고 문제가 없으면 내 문제를 해결할 수없는 상황을 거의 찾지 않지만 궁금한 점은 ...
응용 프로그램에서 리플렉션을 사용한 사용자의 경우 성능 적중을 측정 한 적이 있습니까?
답변:
그것은. 그러나 그것은 당신이하려는 일에 달려 있습니다.
리플렉션을 사용하여 어셈블리 (플러그인)를 동적으로로드하고 성능 "불이익"은 문제가되지 않습니다. 작업은 응용 프로그램 시작 중에 수행하는 작업이기 때문입니다.
그러나 각각에 대해 리플렉션 호출을 사용하여 일련의 중첩 루프 내부에 반영하는 경우 코드를 다시 방문해야한다고 말하고 싶습니다. :)
"몇 시간"작업의 경우 리플렉션을 완벽하게 수용 할 수 있으며 지연이나 문제가 발생하지 않습니다. 매우 강력한 메커니즘이며 .NET에서도 사용되므로 시도하지 말아야 할 이유를 모르겠습니다.
Jeff Richter는 자신의 강연 에서 일상적인 것들의 성능 (Performance of Everyday Things )을 통해 리플렉션을 통해 메서드를 호출하는 것이 일반적으로 호출하는 것보다 약 1000 배 느립니다 .
Jeff의 팁 : 메소드를 여러 번 호출해야하는 경우 리플렉션을 한 번 사용하여 찾은 다음 델리게이트에 할당 한 다음 델리게이트 를 호출하십시오.
리플렉션 성능은 구현에 따라 다릅니다 (예 : 반복 호출을 캐시해야 함 entity.GetType().GetProperty("PropName")
). 매일 보는 대부분의 리플렉션은 데이터 리더 또는 다른 리포지토리 유형 구조에서 엔터티를 채우는 데 사용되므로 개체 속성을 가져 오거나 설정할 때 리플렉션에 대한 성능을 구체적으로 벤치 마크하기로 결정했습니다.
반복되는 모든 호출을 캐시하고 실제 SetValue 또는 GetValue 호출의 시간 만 캐시하기 때문에 공정하다고 생각되는 테스트를 고안했습니다. 성능 테스트를위한 모든 소스 코드는 https://bitbucket.org/grenade/accessortest 에서 bitbucket에 있습니다 . 면밀히 검토하고 격려하십시오.
내가 얻은 결론은 반사 구현이 잘 수행 될 때 한 번에 100,000 행 미만을 반환하는 데이터 액세스 계층에서 반사를 제거하기 위해 실용적이지 않고 눈에 띄는 성능 개선을 제공하지 않는다는 것입니다.
위의 그래프는 저의 작은 벤치 마크의 결과를 보여 주며 반사를 능가하는 메커니즘은 100,000 사이클 마크 후에 만 눈에 띄게 나타납니다. 대부분의 DAL은 한 번에 수백 또는 수천 행만 반환하며 이러한 수준에서는 반향이 잘 수행됩니다.
루프가 아닌 경우 걱정하지 마십시오.
저의 가장 적절한 경험은 큰 개체 모델에서 같은 유형의 두 데이터 엔터티를 속성별로 비교하는 코드를 작성하는 것이 었습니다. 제대로 작동하고 시도해 보았지만 개처럼 달렸습니다.
나는 낙담했지만 밤새 논리를 바꾸지 않고 동일한 알고리즘을 사용하여 비교를 수행하지만 속성에 정적으로 액세스하는 메소드를 자동 생성 할 수 있다는 것을 깨달았다. 이 목적을 위해 코드를 수정하는 데 시간이 전혀 걸리지 않았으며 객체 모델이 변경 될 때마다 버튼을 클릭하면 업데이트 될 수있는 정적 코드로 엔티티를 속성별로 비교할 수있는 능력이있었습니다.
내 요점 : 동료들과의 대화에서 여러 번 반영한 이후로 리플렉션을 사용하면 런타임 작업을 수행하는 대신 컴파일하기 위해 코드를 자동 생성하는 것이 가능하며 종종 고려할 가치가 있다고 지적했습니다.
대규모가 아닙니다. Martin이 말했듯이 바보 같은 위치에서 사용하지 않는 한 데스크톱 개발에서 문제가 발생하지 않았습니다. 많은 사람들이 데스크톱 개발 성능에 대해 전혀 비이성적 인 두려움을 가지고 있다고 들었습니다.
에서 Compact Framework에서 (나는 보통에있어)하지만, 그것은 거의의 저주 대부분의 경우 전염병처럼 피해야한다. 나는 그것을 자주 사용하지 않고 도망 칠 수는 있지만 재미가 덜한 응용 프로그램에는 실제로주의해야합니다. :(
성능에 중요한 코드를 위해 .NET 라이브러리에서 내부적으로 수행 한 리플렉션에 대해서도 걱정해야 할 정도로 나쁩니다.
다음 예제는 더 이상 사용되지 않습니다 (2008 년). 그러나 최근에는 최신 CLR 버전에서 수정되었습니다. 일반적으로 반사는 여전히 다소 비용이 많이 드는 것입니다!
적절한 예 : 고성능 코드의 lock (C #) / SyncLock (VB.NET) 문에서 "Object"로 선언 된 멤버를 사용해서는 안됩니다. 왜? CLR은 값 형식을 잠글 수 없으므로 런타임 리플렉션 형식 검사를 수행하여 Object가 실제로 참조 형식이 아닌 값 형식인지 확인해야합니다.
프로그래밍의 모든 것과 마찬가지로 성능 비용과 이익을 균형있게 유지해야합니다. 리플렉션은주의해서 사용할 때 매우 유용한 도구입니다. 리플렉션을 사용하여 바인딩을 수행하는 C #에서 O / R 매핑 라이브러리를 만들었습니다. 이것은 환상적으로 잘 작동했습니다. 대부분의 리플렉션 코드는 한 번만 실행되었으므로 성능 저하는 거의 없었지만 이점은 컸습니다. 새로운 부채꼴 정렬 알고리즘을 작성하는 경우 아마도 크기가 제대로 조정되지 않기 때문에 리플렉션을 사용하지 않을 것입니다.
귀하의 질문에 정확하게 답변하지 않은 것에 대해 감사드립니다. 내 요점은 실제로 중요하지 않다는 것입니다. 적절한 곳에 반사를 사용하십시오. 사용 방법과시기를 배우는 데 필요한 또 다른 언어 기능 일뿐입니다.
리플렉션은 오브젝트를 자주 생성하는 데 사용하면 성능에 현저한 영향을 줄 수 있습니다. Composite UI Application Block을 기반으로 응용 프로그램을 개발했습니다.리플렉션에 크게 의존하는 을 . 리플렉션을 통한 객체 생성과 관련하여 눈에 띄는 성능 저하가있었습니다.
그러나 대부분의 경우 리플렉션 사용에는 문제가 없습니다. 일부 어셈블리를 검사 해야하는 경우 매우 가볍고 빠른 Mono.Cecil 을 권장합니다.
반영은 매개 변수 목록과 일치하는 메소드를 요청할 때마다 런타임에서 수행해야하는 많은 검사로 인해 비용이 많이 듭니다. 내부 어딘가에 코드의 유형에 대한 모든 메소드를 반복하고, 가시성을 확인하고, 리턴 유형을 확인하고, 각 매개 변수의 유형을 확인합니다. 이 모든 것은 시간이 걸립니다.
해당 메소드를 내부적으로 실행할 때 실제 대상 메소드를 실행하기 전에 호환 가능한 매개 변수 목록을 전달했는지 확인하는 것과 같은 일부 코드가 있습니다.
가능하면 나중에 계속해서 재사용 할 경우 메소드 핸들을 캐시하는 것이 좋습니다. 모든 좋은 프로그래밍 팁과 마찬가지로 자주 반복하지 않는 것이 좋습니다. 이 경우 지속적으로 특정 매개 변수를 사용하여 메서드를 조회 한 다음 매번 실행하는 것이 낭비입니다.
소스를 둘러보고 수행중인 작업을 살펴보십시오.
모든 것과 마찬가지로 상황을 평가하는 것이 전부입니다. 에서 DotNetNuke의 라는 매우 핵심 구성 요소가있다FillObject
사용하는 반사가 데이터 행에서 오브젝트를 채우는 것으로는.
이것은 매우 일반적인 시나리오이며 MSDN에 대한 리플렉션을 사용하여 비즈니스 개체를 ASP.NET 폼 컨트롤에 바인딩 하는 기사가 있습니다. 에서 성능 문제를 다루는 있습니다.
성능을 제외하고는 특정 시나리오에서 리플렉션을 사용하는 것이 마음에 들지 않는 한 가지 점은 코드를 한눈에 이해할 수있는 능력을 줄이는 경향이 있다는 것입니다. LINQ to SQL 과 같은 강력한 형식의 데이터 세트와 달리 시간 안전성 .
리플렉션은 앱 성능을 크게 저하시키지 않습니다. 리플렉션을 사용하지 않으면 서 특정 작업을 더 빨리 수행 할 수 있지만 리플렉션이 일부 기능을 달성하는 가장 쉬운 방법이라면 사용하십시오. 퍼포먼스 문제가된다면 리플렉션에서 코드를 리팩터링 할 수 있습니다.