UFO ET IT

방법 / 속성을 가상으로 표시하면 성능에 어떤 영향이 있습니까?

ufoet 2020. 11. 22. 20:57
반응형

방법 / 속성을 가상으로 표시하면 성능에 어떤 영향이 있습니까?


질문은 제목에 명시된대로입니다. 방법 / 속성을 가상으로 표시하면 성능에 어떤 영향이 있습니까?

참고- 일반적인 경우 가상 메서드가 오버로드 되지 않는다고 가정합니다 . 저는 보통 여기서 기본 클래스로 작업 할 것입니다.


가상 함수는 직접 호출에 비해 성능 오버 헤드가 매우 적습니다. 낮은 수준에서 기본적으로 함수 포인터를 얻기 위해 배열 조회를보고 함수 포인터를 통해 호출합니다. 최신 CPU는 분기 예측 자에서 간접 함수 호출을 합리적으로 잘 예측할 수 있으므로 일반적으로 최신 CPU 파이프 라인을 너무 심하게 손상시키지 않습니다. 어셈블리 수준에서 가상 함수 호출 I은 임의의 즉치 값인 다음과 같이 변환됩니다 .

MOV EAX, [EBP + I] ; Move pointer to class instance into register
MOV EBX, [EAX] ;  Move vtbl pointer into register.
CALL [EBX + I]  ;   Call function

Vs. 직접 함수 호출의 경우 다음과 같습니다.

CALL I  ;  Call function directly

실제 오버 헤드는 대부분의 경우 가상 기능을 인라인 할 수 없다는 점입니다. (VM이 항상 동일한 주소로 이동한다는 것을 VM이 인식하는 경우 JIT 언어 일 수 있습니다.) 인라이닝 자체에서 얻는 속도 향상 외에도 호출자가 수신자가 어떻게 수신자인지 알 수 있기 때문에 인라인은 상수 접기와 같은 여러 다른 최적화를 가능하게합니다. 내부적으로 작동합니다. 어쨌든 인라인되지 않을만큼 충분히 큰 함수의 경우 성능 저하는 무시할 수있을 것입니다. 인라인 될 수있는 매우 작은 함수의 경우 가상 함수에 대해주의해야합니다.

편집 : 명심해야 할 또 다른 사항은 모든 프로그램에 흐름 제어가 필요하다는 것입니다. 가상 기능을 대체하는 것은 무엇입니까? switch 문? 일련의 if 문? 이들은 여전히 ​​예측할 수없는 분기입니다. 또한 N-way 분기가 주어지면 일련의 if 문은 O (N)에서 적절한 경로를 찾는 반면 가상 함수는 O (1)에서 해당 경로를 찾습니다. switch 문은 점프 테이블에 최적화되었는지 여부에 따라 O (N) 또는 O (1) 일 수 있습니다.


Rico Mariani는 Performance Tidbits 블로그 에서 성능 관련 문제를 설명 하며 다음과 같이 말했습니다.

가상 방법 : 직접 호출이 가능할 때 가상 방법을 사용하고 있습니까? 많은 경우 사람들은 미래의 확장 성을 위해 가상 방법을 사용합니다. 확장 성은 좋은 일이지만 대가가 따릅니다. 전체 확장 성 스토리가 해결되고 가상 기능을 사용하여 실제로 필요한 곳으로 이동할 수 있는지 확인하십시오. 예를 들어, 때때로 사람들은 호출 사이트 문제를 통해 생각하지만 "확장 된"개체가 어떻게 만들어 질지 고려하지 않습니다. 나중에 그들은 (대부분) 가상 기능이 전혀 도움이되지 않았고 "확장 된"객체를 시스템으로 가져 오기 위해 완전히 다른 모델이 필요하다는 것을 깨달았습니다.

봉인 : 봉인은 클래스의 다형성을 다형성이 필요한 사이트로 제한하는 방법이 될 수 있습니다. 유형을 완전히 제어 할 경우 실링은 직접 호출 및 인라인을 가능하게하므로 성능면에서 좋은 점이 될 수 있습니다.

기본적으로 가상 메서드에 대한 주장은 직접 호출과 달리 코드가 인라인 후보가되는 것을 허용하지 않는다는 것입니다.

MSDN 문서 Improving .NET Application Performance and Scalability 에서 이에 대해 자세히 설명합니다.

가상 회원의 장단점 고려

확장 성을 제공하려면 가상 멤버를 사용하십시오. 클래스 디자인을 확장 할 필요가없는 경우 가상 테이블 조회로 인해 호출 비용이 더 많이 들고 특정 런타임 성능 최적화를 무효화하므로 가상 멤버를 사용하지 마십시오. 예를 들어, 가상 멤버는 컴파일러에 의해 인라인 될 수 없습니다. 또한 하위 입력을 허용하면 실제로 소비자에게 매우 복잡한 계약을 제시하고 나중에 클래스를 업그레이드하려고 할 때 필연적으로 버전 문제가 발생합니다.

그러나 위의 내용에 대한 비판은 TDD / BDD 진영 (가상으로 기본 설정하는 방법을 원하는 사람)에서 발생하며, 성능 영향은 무시할 수 있으며 특히 훨씬 더 빠른 시스템에 액세스 할 수 있다고 주장합니다.


일반적으로 가상 메서드는 실제 메서드에 도달하기 위해 단순히 하나의 함수 포인터를 통과합니다. 이것은 하나의 추가 역 참조와 메모리에 대한 또 다른 왕복을 의미합니다.

비용이 절대적으로 0은 아니지만 극히 최소화됩니다. 프로그램이 가상 기능을 갖는 데 도움이된다면 반드시 그렇게하십시오.

v 테이블을 피하기 위해 서투른 프로그램보다 작고 작고 작은 성능 히트로 잘 설계된 프로그램을 갖는 것이 훨씬 낫습니다.


.NET JIT 컴파일러가 일부 (많은?) 경우에서 오버 헤드를 최적화 할 수 있기 때문에 확실하게 말하기는 어렵습니다.

그러나 최적화되지 않으면 기본적으로 추가 포인터 간접에 대해 이야기하고 있습니다.

즉, 비가 상 메서드를 호출 할 때

  1. 레지스터를 저장하고, 함수 프롤로그 / 에필로그를 생성하여 인수를 설정하고, 반환 값 등을 복사합니다.
  2. 고정되고 정적으로 알려진 주소로 이동

1은 두 경우 모두 동일합니다. 2의 경우 가상 메서드를 사용하면 대신 객체의 vtable에있는 고정 오프셋에서 읽은 다음 해당 지점으로 점프해야합니다. 이는 분기 예측을 어렵게 만들고 일부 데이터를 CPU 캐시 밖으로 밀어 낼 수 있습니다. 따라서 차이는 크지 않지만 모든 함수 호출을 가상으로 만들면 합산 될 수 있습니다.

또한 최적화를 방해 할 수 있습니다. 컴파일러는 호출되는 함수를 정확히 알고 있기 때문에 비가 상 함수에 대한 호출을 쉽게 인라인 할 수 있습니다. 가상 기능을 사용하면 약간 까다 롭습니다. 어떤 함수가 호출되는지 결정되면 JIT 컴파일러는 여전히이를 수행 할 수 있지만 훨씬 더 많은 작업이 필요합니다.

대체로, 특히 성능이 중요한 영역에서 여전히 추가 될 수 있습니다. 그러나 함수가 초당 수십만 번 이상 호출되지 않는 한 걱정할 필요가 없습니다.


태그에서 c #을 사용하고 있습니다. 델파이 관점에서만 대답 할 수 있습니다. 비슷할 것 같아요. (나는 여기에 부정적인 피드백을 기대하고 있습니다 :))

정적 메서드는 컴파일 타임에 연결됩니다. 가상 메서드는 호출 할 메서드를 결정하기 위해 런타임에 조회가 필요하므로 약간의 오버 헤드가 있습니다. 메서드가 작고 자주 호출되는 경우에만 중요합니다.


이 테스트를 C ++로 실행했습니다 . 가상 함수 호출은 직접 함수 호출보다 7-20 나노초 (3ghz PowerPC에서)가 더 오래 걸립니다. 즉, 초당 백만 번 호출하려는 함수 또는 너무 작아서 오버 헤드가 함수 자체보다 클 수있는 함수에만 중요합니다. (예를 들어, 접근 자 기능을 맹목적인 습관에서 가상으로 만드는 것은 아마도 현명하지 못합니다.)

C #으로 테스트를 실행하지는 않았지만 CLR의 거의 모든 작업이 어쨌든 간접적 인 작업을 포함하기 때문에 차이가 훨씬 적을 것으로 예상합니다.


데스크톱 측에서는 메서드가 오버로드되었는지 여부는 중요하지 않습니다. 메서드 포인터 테이블 (가상 메서드 테이블)을 통해 추가 수준의 간접 지정이 발생합니다. 즉, 메서드 호출이 a를 비교하기 전에 간접을 통해 대략 2 개의 추가 메모리를 읽습니다. 봉인되지 않은 클래스 및 최종적이지 않은 메서드에 대한 비가 상 메서드.

[흥미로운 사실은 컴팩트 프레임 워크 버전 1.0에서는 가상 메소드 테이블을 사용하지 않고 단순히 리플렉션을 사용하여 가상 메소드를 호출 할 때 실행할 올바른 메소드를 발견하기 때문에 과열이 더 큽니다.]

또한 가상 메서드는 비가 상 메서드보다 인라인 또는 꼬리 호출과 같은 기타 최적화 후보가 될 가능성이 훨씬 적습니다.

대략 다음은 메서드 호출의 성능 계층입니다.

Non virtual methods < Virtual Metods < Interface methods (on classes) < Delegate dispatch < MethodInfo.Invoke < Type.InvokeMember

But none of these performance implications of various dispatch mechanisms don't matter unless you proven it by measuring ;) (And even then the architecture implications, readability etc might have a big weight on which one to chose)

참고URL : https://stackoverflow.com/questions/530799/what-are-the-performance-implications-of-marking-methods-properties-as-virtual

반응형