Interop 的效能考量 (C++)
本主題提供降低 Managed/Unmanaged Interop 轉換對運行時間效能的影響的指導方針。
Visual C++支援與其他 .NET 語言相同的互操作性機制,例如 Visual Basic 和 C# (P/Invoke),但也提供 Visual C++ (C++ Interop) 特有的 Interop 支援。 對於效能關鍵性應用程式,請務必瞭解每個 Interop 技術的效能影響。
不論所使用的 Interop 技術為何,每次 Managed 函式呼叫 Unmanaged 函式時,都需要特殊的轉換序列稱為 Thunks,反之亦然。 這些 thunk 是由Microsoft C++編譯程序自動插入,但請務必記住,累計而言,這些轉換在效能方面可能很昂貴。
減少轉換
避免或降低 Interop Thunks 成本的其中一種方法是重構相關的介面,以將 Managed/Unmanaged 轉換降到最低。 透過以閒聊介面為目標,可大幅改善效能,這些介面涉及跨受控/非受控界限頻繁呼叫的介面。 例如,在緊密迴圈中呼叫 Unmanaged 函式的 Managed 函式是重構的好候選專案。 如果迴圈本身已移至 Unmanaged 端,或建立 Unmanaged 呼叫的 Managed 替代專案(可能是在 Managed 端排入數據佇列,然後在循環之後一次封送處理至 Unmanaged API),轉換數目可以大幅減少。
P/Invoke 與 C++ Interop
對於 .NET 語言,例如 Visual Basic 和 C#,與原生元件互通的指定方法是 P/Invoke。 因為 .NET Framework 支援 P/Invoke,所以 Visual C++也支援它,但 Visual C++也提供自己的互操作性支援,這稱為 C++ Interop。 C++ Interop 優先於 P/Invoke,因為 P/Invoke 不是類型安全。 因此,錯誤主要是在運行時間報告,但C++ Interop 也具有 P/Invoke 的效能優勢。
每當 Managed 函式呼叫 Unmanaged 函式時,這兩種技術都需要發生數件事:
函式呼叫自變數會從 CLR 封送處理至原生類型。
執行 Managed 到 Unmanaged Thunk。
會呼叫 Unmanaged 函式(使用自變數的原生版本)。
執行 Unmanaged 到 Managed Thunk。
傳回型別和任何「out」或「in」自變數都會從原生封送處理至 CLR 類型。
Managed/Unmanaged Thunks 完全需要 Interop 才能運作,但所需的數據封送處理取決於所涉及的數據類型、函式簽章,以及數據的使用方式。
C++ Interop 所執行的數據封送處理是最簡單的形式:參數只會以位位方式跨 Managed/Unmanaged 界限複製;完全不會執行任何轉換。 針對 P/Invoke,只有在所有參數都是簡單、blittable 類型時,才會是 true。 否則,P/Invoke 會執行非常健全的步驟,將每個 Managed 參數轉換成適當的原生類型,反之亦然,如果自變數標示為「out」或「in,out」。
換句話說,C++ Interop 會使用最快的數據封送處理方法,而 P/Invoke 則使用最強固的方法。 這表示C++ Interop(以C++的典型方式)預設提供最佳效能,而程式設計人員負責處理此行為不安全或不適合的情況。
因此,C++ Interop 需要明確提供數據封送處理,但優點是,程式設計人員可以自由決定數據的性質,以及其使用方式。 此外,雖然 P/Invoke 數據封送處理的行為可以自定義為某個程度進行修改,C++ Interop 允許以呼叫方式自定義數據封送處理。 P/Invoke 無法執行這項作業。
如需C++ Interop 的詳細資訊,請參閱 使用 C++ Interop (隱含 PInvoke) 。