Share via


Windows 執行階段元件和互通性優化

建立使用 Windows 執行階段元件和原生與受控類型之間的互通性,同時可避免互通性效能問題的 Windows 應用程式。

Windows 執行階段元件互通性的最佳做法

如果您不夠謹慎,使用 Windows 執行階段元件有可能對應用程式效能造成很大的影響。 本捷討論如何在應用程式使用 Windows 執行階段元件時獲得良好的效能。

簡介

互通性對於效能可能會有很大的影響,而且您可能正在使用它卻不自覺。 Windows 執行階段會為您處理許多的互通性問題,這樣您就可以提高生產力,並重複使用以其他語言撰寫的程式碼。 我們建議您善加利用 Windows 執行階段的功能,但是請了解它可能會影響效能。 本節討論您可以執行的操作,以減輕互通性對應用程式效能的影響。

Windows 執行階段具有一個類型庫,這個類型庫可從任何可撰寫通用 Windows 平台應用程式的語言存取。 您可以使用 C# 或 Microsoft Visual Basic 中的 Windows 執行階段類型,其使用方式與 .NET 物件的使用方式相同。 您不需要執行平台叫用方法呼叫,就可以存取 Windows 執行階段元件。 這使得撰寫應用程式比較不複雜,但是請務必了解會發生比預期更多的互動性。 如果 Windows 執行階段元件是以非 C# 或 Visual Basic 的語言來撰寫,當您使用該元件時,會跨越互通性界限。 跨越互通性界限可能會影響應用程式的效能。

當您在 C# 或 Visual Basic 中開發 UWP 應用程式時,您使用的兩組最常見的 API 是 Windows 執行階段 API 與適用於 UWP 應用程式的 .NET API。 一般而言,由 Windows 執行階段所提供的類型是建置於 Windows 執行階段中以「Windows」開頭的命名空間,而 .NET 類型則位於開頭為「System.」的命名空間但還是有些例外狀況。 使用適用於 UWP 應用程式的 .NET API 中所列的類型時,並不需要互通性。 如果您發現在使用 Windows 執行階段時效能不佳,可以改用適用於 UWP 應用程式的 .NET,以獲得較佳的效能。

注意 大部分隨附在 Windows 10 中的 Windows 執行階段元件都是以 C++ 實作,因此從 C# 或 Visual Basic 使用這些元件時,可以跨越互通性界限。 一如往常,請務必先評估您的應用程式以了解使用 Windows 執行階段元件是否會影響應用程式的效能,再花費時間和精力變更程式碼。

在這個主題中,當我們提到「Windows 執行階段元件」時,是指以 C# 或 Visual Basic 以外的語言所撰寫的Windows 執行階段元件。

 

每次您在 Windows 執行階段元件存取屬性或是呼叫方法時,都會產生互通性成本。 事實上,建立 Windows 執行階段元件比建立 .NET 物件的成本更高。 這個問題的原因是 Windows 執行階段所執行的程式碼,是從應用程式的語言轉換到元件的語言。 另外,如果您將資料傳遞給元件,在受控和非受控類型之間必須轉換資料。

有效率地使用 Windows 執行階段元件

如果您發現需要獲得較佳的效能,可以確保程式碼盡可能有效使用 Windows 執行階段元件。 本節討論使用 Windows 執行階段元件時改善效能的一些秘訣。

必須在短期間內有大量的呼叫,才能使效能影響顯現出來。 將呼叫從商務邏輯與其他受控程式碼封裝成 Windows 執行階段元件的設計良好的應用程式,應該不會產生龐大的互通性成本。 但是如果您的測試指出使用 Windows 執行階段元件會影響應用程式的效能,則在本節中討論的秘訣可協助您改善效能。

請考慮使用適用於 UWP 應用程式的 .NET 所提供的類型

在某些情況下,您可以使用 Windows 執行階段或適用於 UWP 應用程式的 .NET 所提供的類型來完成工作。 建議您試著不要混合使用 .NET 類型與 Windows 執行階段類型。 試著只使用其中一種或其他種類型。 例如,您可以使用 Windows.Data.Xml.Dom.XmlDocument 類型 (Windows 執行階段類型) 或是 System.Xml.XmlReader 類型 (.NET 類型),來分析 XML 的資料流。 使用來自與資料流相同技術的 API。 例如,如果您從 MemoryStream 讀取 XML,請使用 System.Xml.XmlReader 類型,因為兩個類型都是 .NET 類型。 如果您從檔案讀取,請使用 Windows.Data.Xml.Dom.XmlDocument 類型,因為檔案 API 與 XmlDocument 皆在原生 Windows 執行階段元件中實作。

將 Window 執行階段物件複製到 .NET 類型

Windows 執行階段元件傳回 Windows 執行階段物件時,將傳回的物件複製到 .NET 物件,可能會非常實用。 有兩個地方特別重要,那就是使用集合與資料流時。

如果您呼叫會傳回集合的 Windows 執行階段 API,然後儲存和存取該集合許多次,則將該集合複製到 .NET 集合,並從之後都使用 .NET 版本,可能會非常實用。

快取呼叫 Windows 執行階段元件的結果以供後續使用

您可以將值儲存到區域變數,而不是多次存取 Windows 執行階段類型,以獲得較佳的效能。 如果您使用迴圈中的值,將特別實用。 請評估您的應用程式,以了解使用區域變數是否可改善應用程式的效能。 使用快取的值可以提升應用程式的速度,因為它在互通性上花費較少的時間。

結合對 Windows 執行階段的呼叫

試著盡量以最少數目的 UWP 物件呼叫來完成工作。 例如,通常最好是一次從資料流中讀取大量的資料,而不是讀取少量的資料。

透過將工作包含在盡可能愈少呼叫中的方式來使用 API,而不是透過做比較少的工作但需要更多呼叫的方式來使用 API。 例如,最好透過呼叫會初始化多個屬性的建構函式來建立物件,而不是呼叫預設的建構函式並一次指派一個屬性。

建置 Windows 執行階段元件

如果您撰寫的 Windows 執行階段元件可由 C++ 或 JavaScript 撰寫的應用程式使用,請確定您所設計的元件具有良好的效能。 所有針對如何使應用程式獲得良好效能的建議,也適用於如何使元件獲得良好效能。 請評估您的元件以了解哪些 API 具有高流量模式,而且對於那些部分,請考慮提供可讓使用者以很少的呼叫執行工作的 API。

在受控程式碼中使用互通性時保持應用程式的快速效能

Windows 執行階段可讓原生與受控程式碼之間的互通更為容易,但只要一不注意就很容易產生效能成本。 我們將說明在您的受控 UWP 應用程式中使用互通性時如何獲得最佳效能。

Windows 執行階段可讓開發人員以選擇的語言編寫使用 XAML 的應用程式,這都要歸功於可在每個語言中使用的 Windows 執行階段 API 設計。 以 C# 或 Visual Basic 撰寫應用程式時,互通性雖然方便卻有其代價,因為 Windows 執行階段 API 通常會在機器碼中實作,而任何來自 C# 或 Visual Basic 的 Windows 執行階段叫用會要求 CLR 從受控轉換成原生堆疊框架,然後將函式參數封送處理為機器碼可以存取的表示法。 大部分應用程式會忽略這個額外的成本。 但是當您在某個應用程式的關鍵路徑中多次呼叫 (數十萬到數百萬個呼叫) Windows 執行階段 API 時,這個成本便非常可觀。 一般而言,您會希望語言之間轉換所花的時間比執行程式碼其他部分所花的時間相對較少。 如下圖所示。

Interop transitions should not dominate the program execution time.

適用於 Windows 應用程式的 .NET \(英文\) 中列出的類型從 C# 或 Visual Basic 中使用時不會產生這個互通性成本。 做為經驗法則,您可以假設命名空間中以「Windows.」為開頭的類型 為 Windows 所提供的 Windows 執行階段 API 集之一部分,和以「System.」為開頭的命名空間中之類型 則是 .NET 類型。 請記住,就算是簡單的 Windows 執行階段類型使用 (例如配置或屬性存取) 也會產生互通性成本。

您應該測量應用程式並判斷互通性是否佔用了應用程式大部分執行階段,然後再針對互通性成本進行優化。 使用 Visual Studio 分析應用程式效能前,可以使用 [功能] 檢視並查看呼叫至 Windows 執行階段中的方法所耗費的時間,輕易取得互通性成本上限。

如果您的應用程式因互通性負荷而變慢,您可以在最忙碌的程式碼路徑中減少對 Windows 執行階段 API 的呼叫,以便提高應用程式的效能。 例如,若要在不斷查詢 UIElements 位置和維度以執行大量物理計算的遊戲引擎中節省執行階段,您可以將來自 UIElements 的必要資訊儲存到區域變數,並在這些快取的值上進行計算,然後在計算完成後將最終結果指派回 UIElements。 另一個例子:如果 C# 或 Visual Basic 程式碼大量存取某個集合,則使用 System.Collections 命名空間中的集合比使用 Windows.Foundation.Collections 命名空間中的集合更有效率。 您也可以考慮將 Windows 執行階段元件的呼叫結合起來;可以這樣做的其中一個範例就是使用 Windows.Storage.BulkAccess API。

建置 UWP 元件

如果您撰寫供 C++ 或 JavaScript 撰寫的應用程式使用的 Windows 執行階段元件,請確定您所設計的元件具有良好的效能。 您的 API 表面會定義互通性界限並定義使用者必須思考本主題所述之指導方針的程度。 如果您要將元件發佈給其他人,那麼這就變得異常重要了。

所有針對如何使應用程式獲得良好效能的建議,也適用於如何使元件獲得良好效能。 請評估您的元件以了解哪些 API 具有高流量模式,而且對於那些部分,請考慮提供可讓使用者以很少的呼叫執行工作的 API。 為了讓應用程式可以使用 Windows 執行階段而不需經常跨越互通性界限,在 Windows 執行階段的設計上花費了許多精力。