HOW TO:改善效能

更新:2007 年 11 月

下列程式設計作法可以節省記憶體,並改善裝置應用程式的效能。

若要利用 Windows Form 和圖形節省記憶體

若要利用資料和字串節省記憶體

  • 請在 for 迴圈 (Loop) 中使用整數變數 (Int32Int64),而不要使用物件變數。

  • 請避免使用列舉型別的 ToString 方法,因為它在搜尋中繼資料表時會影響效能。

  • 避免 OutOfMemoryException 錯誤。當沒有足夠的記憶體可配置給內部用途或新物件執行實體時,Common Language Runtime 會擲回此例外狀況。若要避免此例外狀況,請避免設計會使用 64 KB 或更多記憶體之大型方法的程式。

  • 請移除 System.SR.dll,其中含有例外狀況對話方塊的錯誤訊息字串。您可以在沒有這個檔案的情況下部署應用程式,以節省記憶體。如果檔案已經存在,.NET Compact Framework 會動態載入包含在 System.SR.dll 中的錯誤字串。

    如果裝置上沒有此 .dll 檔案,所有的例外狀況都會包含「無法載入資源組件」的訊息。然而在開發期間,將 System.SR.dll 的參考加入至 Visual Studio 專案會很有用,如此您就會看到有意義的例外狀況。

  • 字串是不可變動的,因此,每當您修改字串時,都會建立新的 String 物件。在建構將會經常修改的字串時,請考慮使用 StringBuilder

  • 如果您知道 DateTime 序列化 (Serialization) 所使用的確切格式,請對 DateTime 使用 ParseExact 方法。否則,DateTime 剖析器 (Parser) 將會循序嘗試套用數種文化特性特定的格式。

  • 限制開啟 SqlCeCommand 物件的數目,並在完成時處置 (Dispose) 這些物件。

若要在與機器碼相互操作時節省記憶體

  • 請在平台叫用作業中使用 Blittable 型別,該型別在 Managed 和 Unmanaged 記憶體中都具有通用的表示,例如 Int32IntPtr。透過傳址 (By Reference) 方式傳遞大於 32 位元的 Blittable 實值型別,會比使用傳值 (By Value) 的方式更迅速。如需 Blittable 型別的詳細資訊,請參閱 .NET Compact Framework Blittable 型別

  • 請在函式簽章 (Signature) 中使用引數的 InAttributeOutAttribute 屬性,以減少不必要的封送處理 (Marshaling)。

  • 請使用 Marshal 類別中的方法,以手動方式在 IntPtr 和 Managed 物件之間進行轉換,例如 PtrToStructurePtrToStringBSTRGetObjectForNativeVariantGetObjectForIUnknown

  • 請使用 PrelinkPrelinkAll 方法,讓支援機器碼至 Managed 呼叫的 Stub 可以進行 JIT 編譯。

  • 如果您要原生 COM 物件如同一般情況傳回 S_FALSE,或傳回其他非 S_OK HRESULT 值,請將 PreserveSig 欄位設定為 true,並使 Managed 簽章符合原生簽章。如此,在執行階段將 COM 呼叫上的 HRESULT 值轉譯為例外狀況時,即可避免必要的 try/catch 區塊發生額外負荷。

  • 請盡可能在一次平台叫用呼叫中完成工作,而不要使用多次呼叫。

若要在集合中節省記憶體

  • 如果集合是以陣列為基礎,請使用索引子 (Indexer)。

  • 由於動態調整大小可能會大幅地增加過多儲存體,因此,在可能的情況下請盡量指定集合的大小。

  • 請使用泛型集合,以避免 Boxing 和 Unboxing 實值型別發生額外負荷。定義屬於自己的最佳化集合,便可以達到最佳的效能。

若要在 XML 中節省記憶體

  • 請使用 XmlTextReaderXmlTextWriter,而不要使用 XmlDocument,因為後者會用掉更多記憶體。

  • 請指定 XmlReaderSettingsXmlWriterSettings 的設定以改善效能。如果適用的話,IgnoreWhitespaceIgnoreComments 屬性值也可以顯著改善效能。

  • 請使用 UTF-8、ASCII 及 UTF-16 字元編碼方式,這些比 ANSI 和 Windows 字碼頁編碼方式還快。

  • 請避免使用結構描述進行剖析,因為這樣會需要額外的驗證工作。

  • 請將資料行對應做為屬性,並在從 XML 來源填入 DataSet 時,使用具型別 DataSet

  • 在填入 DataSet 時請避免下列各項:

    • 結構描述推斷

    • 巢狀資料表

    • 數個 DateTime 資料行。如需達成更佳的效能,請改用 Ticks 屬性值

  • 下列方針有助於改善使用 XML 還原序列化 (Deserialization) 時的效能:

    • 由於每個字元都必須進行驗證,請將項目和屬性名稱盡量保持簡短。

    • 以屬性資料為基礎的 XML,會比以項目資料為基礎的 XML 還快。

    • 請適時使用 XmlNodeReader.Skip 方法。

    • 當效能成為第一優先考量時,請使用二進位序列化。

  • 讓每個型別使用一個 XmlSerializer 執行個體來進行 XML 序列化,以減少搜尋中繼資料的時間。

  • 由於序列化大量 XML 可能會用盡記憶體,請考慮使用 BinaryReaderBinaryWriter,改為建立自訂的二進位序列化機制。

若要在使用 Web 服務時節省記憶體

  • 請在讀取和寫入 DataSet 時使用 DiffGram。如需詳細資訊,請參閱 DiffGrams (ADO.NET)

  • 請將遠端 DataSet 及它的結構描述儲存至裝置,做為 XML。

  • 由於第一次呼叫比後續的呼叫緩慢,請在啟動顯示畫面進行簡單的 Web 服務方法呼叫。

  • 請小心處理網路和資料錯誤。

  • 在某些情況下,先將 DataSet 手動序列化為 XML 字串之後再進行 Web 服務呼叫,可以產生更佳的效能。

若要在進階程式設計中節省記憶體

  • 非同步處理大型作業。

  • 避免虛擬呼叫。比起靜態或執行個體呼叫,.NET Compact Framework 執行階段虛擬呼叫大約慢了 30%。由於資源有限,.NET Compact Framework 不會使用 Vtable,因此必須往返類別和介面階層架構才能呼叫方法,而這是非常耗用資源的作業。.NET Compact Framework 會維護已解析之虛擬呼叫的快取,因此在多數情況下,並不需要重新解譯呼叫。

  • 請盡可能使用欄位而非屬性。

  • 請在定義實值型別時覆寫 GetHashCodeEquals 方法。如果沒有覆寫這兩個方法,執行階段便會在基底 ValueType 類別中使用這些方法的通用版本。

  • Use reflection with caution.對於未具現化 (Instantiated) 的類別,為了檢查目的而使用反映,可能會影響應用程式中具現化物件的效能。

  • 請確定 Managed 資源具有完整型別名稱,並且在 RESX 檔案中也是正確的。這些資源必須具備正確版本和 PublicKeyToken 欄位。為不當指定的型別尋找最適當的替代型別,將會影響效能。

  • 請注意,在某些情況下,從檔案直接讀取應用程式資料可能已經足夠,並且會比使用 ResourceManager 更有效率。ResourceManager 可能會在找出資源二進位檔之前,先探查檔案系統中的多個位置,以找出最相符的附屬組件。請針對工作使用適當的工具。

請參閱

概念

.NET Compact Framework 中的裝置記憶體管理

.NET Compact Framework HOW TO 主題

其他資源

.NET Compact Framework 中的效能和診斷