共用方式為


Interop 的效能考量 (C++)

本主題提供降低 Managed/Unmanaged Interop 轉換對執行時間效能的影響的指導方針。

Visual C++ 支援與其他 .NET 語言相同的互通性機制,例如 Visual Basic 和 C# (P/Invoke),但也提供 Visual C++ 特有的 Interop 支援(C++ Interop)。 對於效能關鍵性應用程式,請務必瞭解每個 Interop 技術的效能影響。

不論所使用的 Interop 技術為何,每次 Managed 函式呼叫 Unmanaged 函式時,都需要特殊的轉換序列稱為 Thunks,反之亦然。 Microsoft C++ 編譯器會自動插入這些 Thunk,但請務必記住,累計而言,這些轉換在效能方面可能很昂貴。

減少轉換

避免或降低 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++ Interop 需要明確提供資料封送處理,但優點是,程式設計人員可以自由決定資料的性質,以及其使用方式。 此外,雖然 P/Invoke 資料封送處理的行為可以自訂為某個程度進行修改,但 C++ Interop 允許逐次呼叫自訂資料封送處理。 P/Invoke 無法執行這項作業。

如需 C++ Interop 的詳細資訊,請參閱 使用 C++ Interop (隱含 PInvoke)

另請參閱

混合 (原生和 Managed) 組件