Interop에 대한 성능 고려 사항(C++)
이 항목에서는 관리/비관리 interop 전환이 런타임 성능에 미치는 영향을 줄이기 위한 지침을 제공합니다.
Visual C++는 Visual Basic이나 C# 같은 다른 .NET 언어와 동일한 상호 운용성 메커니즘(P/Invoke)을 지원할 뿐만 아니라 Visual C++에만 적용되는 interop 지원(C++ interop)도 제공합니다. 성능을 크게 고려해야 하는 응용 프로그램에서는 각 interop 기술이 성능에 미칠 수 있는 영향을 이해하는 것이 중요합니다.
어떠한 interop 기술을 사용하건 상관없이 관리되는 함수가 관리되지 않는 함수를 호출하거나 그 반대로 호출할 때마다 썽크라는 특별한 전환 시퀀스가 필요합니다. 이러한 썽크는 Visual C++ 컴파일러에서 자동으로 삽입되지만 이와 같은 전환은 누적되므로 성능이 저하될 수도 있다는 점을 염두에 둘 필요가 있습니다.
전환 줄이기
interop 썽크에 따른 성능 저하를 막거나 줄이기 위한 방법 중 하나로 관리/비관리 전환을 최소화하는 데 관련된 인터페이스를 리팩터링할 수 있습니다. 관리/비관리 경계를 넘나드는 잦은 호출과 관련하여 자주 사용되는 인터페이스를 대상으로 리팩터링하면 성능을 크게 향상시킬 수 있습니다. 예를 들어, 자주 반복되는 루프에서 관리되지 않는 함수를 호출하는 관리되는 함수를 리팩터링하면 큰 효과를 볼 수 있습니다. 루프 자체를 관리되지 않는 영역으로 옮기거나 (관리되는 영역에 데이터 큐를 대기시킨 다음 루프 이후에 이를 모두 한 번에 관리되지 않는 API로 마샬링하여) 관리되지 않는 호출에 상응하는 관리되는 호출을 만들어 전환 수를 크게 줄일 수도 있습니다.
P/Invoke vs. C++ Interop
Visual Basic 및 C# 같은 .NET 언어의 경우 네이티브 구성 요소와 상호 운용하기 위한 기본 방법은 P/Invoke입니다. P/Invoke는 .NET Framework에서 지원하므로 Visual C++도 이를 지원하지만 Visual C++에서는 C++ Interop라는 자체 상호 운용성 지원 기능도 제공합니다. P/Invoke는 형식이 안전하지 않으므로 P/Invoke 대신 C++ Interop를 사용하는 것이 좋습니다. 이 경우 오류가 주로 런타임에 보고되지만 C++ Interop를 사용하면 P/Invoke를 사용할 때보다 성능이 향상되는 이점도 있습니다.
두 기술 모두 관리되는 함수에서 관리되지 않는 함수를 호출할 때마다 여러 단계를 거쳐야 합니다.
함수 호출 인수가 CLR에서 네이티브 형식으로 마샬링됩니다.
관리되는 함수에서 관리되지 않는 함수로의 썽크가 실행됩니다.
네이티브 버전의 인수를 사용하여 관리되지 않는 함수가 호출됩니다.
관리되지 않는 함수에서 관리되는 함수로의 썽크가 실행됩니다.
반환 형식과 모든 "out" 또는 "in,out" 인수가 네이티브 형식에서 CLR 형식으로 마샬링됩니다.
관리/비관리 썽크는 interop 작동에 반드시 필요하지만, 어떠한 데이터 마샬링이 필요한지는 관련된 데이터 형식, 함수 시그니처, 데이터를 사용하는 방식에 따라 달라집니다.
C++ Interop에서 수행하는 데이터 마샬링은 가장 간단한 형태입니다. 비트 방식으로 관리/비관리 경계 너머로 매개 변수를 복사하기만 하고 변환은 전혀 수행하지 않습니다. P/Invoke의 경우 이러한 방식은 모든 매개 변수가 단순한 blittable 형식인 경우에만 적용됩니다. 그렇지 않으면 P/Invoke는 인수가 "out" 또는 "in,out"으로 표시되어 있는 경우 관리되는 각 매개 변수를 해당 네이티브 형식으로 변환하거나 그 반대로 변환하기 위한 매우 강력한 단계를 수행합니다.
즉, C++ Interop에서는 가능한 한 속도가 빠른 데이터 마샬링 방법을 사용하는 반면 P/Invoke에서는 가능한 한 강력한 방법을 사용합니다. 따라서 C++에 일반적으로 사용되는 방식인 C++ Interop는 기본적으로 최적화된 성능을 제공하며, 이 동작이 안전하지 않거나 적합하지 않은 경우에 발생하는 문제는 프로그래머가 직접 처리해야 합니다.
C++ Interop의 경우 데이터 마샬링을 명시적으로 제공해야 하지만 데이터의 성격과 데이터가 사용되는 방식을 지정하면 더 적합한 기술을 프로그래머가 직접 결정하지 않아도 된다는 이점이 있습니다. 또한 P/Invoke 데이터 마샬링 동작도 어느 정도까지는 사용자 지정하여 수정할 수 있지만 C++ Interop의 경우에는 데이터 마샬링을 각 호출별로 사용자 지정할 수 있습니다. P/Invoke에서는 이러한 융통성을 발휘할 수 없습니다.
C++ Interop에 대한 자세한 내용은 C++ Interop 사용(암시적 PInvoke)을 참조하십시오.