第 8 章 — 智能客戶端應用程序性能
智能客戶端體系結構與設計指南
David Hill、Brenton Webster、Edward A. Jezierski、Srinath Vasireddy、Mohammad Al-Sabt,Microsoft Corporation,Blaine Wastell Ascentium Corporation,Jonathan Rasmusson 和 Paul Gale ThoughtWorks 和 Paul Slater Wadeware LLC
相關鏈接
Microsoft? patterns & practices 庫 http://www.microsoft.com/resources/practices/default.mspx
.NET 的應用程序體系結構:設計應用程序和服務http://msdn.microsoft.com/library/en-us/dnbda/html/distapp.asp
摘要:本章討論如何優化您的智能客戶端應用程序。本章分析您可以在設計時采取的步驟,并介紹如何調整智能客戶端應用程序以及診斷任何性能問題。

本頁內容
![]() |
針對性能進行設計 |
![]() |
性能調整和診斷 |
![]() |
小結 |
![]() |
參考資料 |
智能客戶端應用程序可以提供比 Web 應用程序更豐富和響應速度更快的用戶界面,并且可以利用本地系統資源。如果應用程序的大部分駐留在用戶的計算機上,則應用程序不需要到 Web 服務器的持續的往返行程。這有利于提高性能和響應性。然而,要實現智能客戶端應用程序的全部潛能,您應該在應用程序的設計階段仔細考慮性能問題。通過在規劃和設計您的應用程序時解決性能問題,可以幫助您及早控制成本,并減小以后陷入性能問題的可能性。
注改善智能客戶端應用程序的性能并不僅限于應用程序設計問題。您可以在整個應用程序生存期中采取許多個步驟來使 .NET 代碼具有更高的性能。雖然 .NET 公共語言運行庫 (CLR) 在執行代碼方面非常有效,但您可以使用多種技術來提高代碼的性能,并防止在代碼級引入性能問題。有關這些問題的詳細信息,請參閱http://msdn.microsoft.com/perf。
在應用程序的設計中定義現實的性能要求并識別潛在的問題顯然是重要的,但是性能問題通常只在編寫代碼之后對其進行測試時出現。在這種情況下,您可以使用一些工具和技術來跟蹤性能問題。
本章分析如何設計和調整您的智能客戶端應用程序以獲得最佳性能。它討論了許多設計和體系結構問題(包括線程處理和緩存注意事項),并且分析了如何增強應用程序的 Windows 窗體部分的性能。本章還介紹了您可以用來跟蹤和診斷智能客戶端應用程序性能問題的一些技術和工具。
針對性能進行設計
您可以在應用程序設計或體系結構級完成許多工作,以確保智能客戶端應用程序具有良好的性能。您應該確保在設計階段盡可能早地制定現實的且可度量的性能目標,以便評估設計折衷,并且提供最劃算的方法來解決性能問題。只要可能,性能目標就應該基于實際的用戶和業務要求,因為這些要求受到應用程序所處的操作環境的強烈影響。性能建模是一種結構化的且可重復的過程,您可以使用該過程來管理您的應用程序并確保其實現性能目標。有關詳細信息,請參閱 Improving .NET Application Performance and Scalability 中的第 2 章“Performance Modeling”,網址為:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag/html/scalenetchapt02.asp。
智能客戶端通常是較大的分布式應用程序的組成部分。很重要的一點是在完整應用程序的上下文中考慮智能客戶端應用程序的性能,包括該客戶端應用程序使用的所有位于網絡中的資源。微調并優化應用程序中的每一個組件通常是不必要或不可能的。相反,性能調整應該基于優先級、時間、預算約束和風險。一味地追求高性能通常并不是一種劃算的策略。
智能客戶端還將需要與用戶計算機上的其他應用程序共存。當您設計智能客戶端應用程序時,您應該考慮到您的應用程序將需要與客戶端計算機上的其他應用程序共享系統資源,例如,內存、CPU 時間和網絡利用率。
注有關設計可伸縮的高性能遠程服務的信息,請參閱Improving .NET Performance and Scalability,網址為:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag/html/scalenet.asp。本指南包含有關如何優化 .NET 代碼以獲得最佳性能的詳細信息。
要設計高性能的智能客戶端,請考慮下列事項:
? |
在適當的位置緩存數據。數據緩存可以顯著改善智能客戶端應用程序的性能,使您可以在本地使用數據,而不必經常從網絡檢索數據。但是,敏感數據或頻繁更改的數據通常不適合進行緩存。 |
? |
優化網絡通訊。如果通過“健談的”接口與遠程層服務進行通訊,并且借助于多個請求/響應往返行程來執行單個邏輯操作,則可能消耗系統和網絡資源,從而導致低劣的應用程序性能。 |
? |
有效地使用線程。如果您使用用戶界面 (UI) 線程執行阻塞 I/O 綁定調用,則 UI 似乎不對用戶作出響應。因為創建和關閉線程需要系統開銷,所以創建大量不必要的線程可能導致低劣的性能。 |
? |
有效地使用事務。如果客戶端具有本地數據,則使用原子事務可幫助您確保該數據是一致的。因為數據是本地的,所以事務也是本地的而不是分布式的。對于脫機工作的智能客戶端而言,對本地數據進行的任何更改都是暫時的。客戶端在重新聯機時需要同步更改。對于非本地數據而言,在某些情況下可以使用分布式事務(例如,當服務位于具有良好連接性的同一物理位置并且服務支持它時)。諸如 Web 服務和消息隊列之類的服務不支持分布式事務。 |
? |
優化應用程序啟動時間。較短的應用程序啟動時間使用戶可以更為迅速地開始與應用程序交互,從而使用戶立刻對應用程序的性能和可用性產生好感。應該對您的應用程序進行適當的設計,以便在應用程序啟動時僅加載那些必需的程序集。因為加載每個程序集都會引起性能開銷,所以請避免使用大量程序集。 |
? |
有效地管理可用資源。低劣的設計決策(例如,實現不必要的完成器,未能在 Dispose 方法中取消終止,或者未能釋放非托管資源)可能導致在回收資源時發生不必要的延遲,并且可能造成使應用程序性能降低的資源泄漏。如果應用程序未能正確地釋放資源,或者應用程序顯式強制進行垃圾回收,則可能會妨礙 CLR 有效地管理內存。 |
? |
優化 Windows 窗體性能。智能客戶端應用程序依靠 Windows 窗體來提供內容豐富且響應迅速的用戶界面.您可以使用多種技術來確保 Windows 窗體提供最佳性能。這些技術包括降低用戶界面的復雜性,以及避免同時加載大量數據。 |
在許多情況下,從用戶角度感受到的應用程序性能起碼與應用程序的實際性能同樣重要。您可以通過對設計進行某些特定的更改來創建在用戶看來性能高得多的應用程序,例如:使用后臺異步處理(以使 UI 能作出響應);顯示進度欄以指示任務的進度;提供相應的選項以便用戶取消長期運行的任務。
本節將專門詳細討論這些問題。
數據緩存原則
緩存是一種能夠改善應用程序性能并提供響應迅速的用戶界面的重要技術。您應該考慮下列選項:
? |
緩存頻繁檢索的數據以減少往返行程。如果您的應用程序必須頻繁地與網絡服務交互以檢索數據,則應該考慮在客戶端緩存數據,從而減少通過網絡重復獲取數據的需要。這可以極大地提高性能,提供對數據的近乎即時的訪問,并且消除了可能對智能客戶端應用程序性能造成不利影響的網絡延遲和中斷風險。 |
? |
緩存只讀引用數據。只讀引用數據通常是理想的緩存對象。此類數據用于提供進行驗證和用戶界面顯示所需的數據,例如,產品說明、ID 等等。因為客戶端無法更改此類數據,所以通常可以在客戶端緩存它而無須進行任何進一步的特殊處理。 |
? |
緩存要發送給位于網絡上的服務的數據。您應該考慮緩存要發送給位于網絡上的服務的數據。例如,如果您的應用程序允許用戶輸入由在多個窗體中收集的一些離散數據項組成的定單信息,則請考慮允許用戶輸入全部數據,然后在輸入過程的結尾在一個網絡調用中發送定單信息。 |
? |
盡量少地緩存高度不穩定的數據。在緩存任何不穩定的數據之前,您需要考慮在其變得陳舊或者由于其他原因變得不可用之前,能夠將其緩存多長時間。如果數據高度不穩定并且您的應用程序依賴于最新信息,則或許只能將數據緩存很短一段時間(如果可以緩存)。 |
? |
盡量少地緩存敏感數據。您應該避免在客戶端上緩存敏感數據,因為在大多數情況下,您無法保證客戶端的物理安全。但是,如果您必須在客戶端上緩存敏感數據,則您通常將需要加密數據,該操作本身也會影響性能。 |
有關數據緩存的其他問題的詳細信息,請參閱本指南的第 2 章。另請參閱 Improving .NET Application Performance and Scalability 的第 3 章“Design Guidelines for Application Performance”(http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag/html/scalenetchapt03.asp) 的“Caching”一節以及 Improving .NET Application Performance and Scalability 的第 4 章“Architecture and Design Review of .NET Application for Performance and Scalability”(http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag/html/scalenetchapt04.asp)。
網絡通訊原則
您將面臨的另一個決策是如何設計和使用網絡服務,例如,Web 服務。特別地,您應該考慮與網絡服務交互的粒度、同步性和頻率。要獲得最佳的性能和可伸縮性,您應該在單個調用中發送更多的數據,而不是在多個調用中發送較少量的數據。例如,如果您的應用程序允許用戶在定單中輸入多個項,則較好的做法是為所有項收集數據,然后將完成的采購定單一次性發送給服務,而不是在多個調用中發送單個項的詳細信息。除了降低與進行大量網絡調用相關聯的系統開銷以外,這還可以減少服務和/或客戶端內的復雜狀態管理的需要。
應該將您的智能客戶端應用程序設計為盡可能地使用異步通訊,因為這將有助于使用戶界面快速響應以及并行執行任務。有關如何使用 BeginInvoke 和 EndInvoke 方法異步啟動調用和檢索數據的詳細信息,請參閱“Asynchronous Programming Overview”(http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpovrasynchronousprogrammingoverview.asp)。
注有關設計和構建偶爾連接到網絡的智能客戶端應用程序的詳細信息,請參閱第 3 章“建立連接”和第 4 章“偶爾連接的智能客戶端”。
線程處理原則
在應用程序內使用多個線程可能是一種提高其響應性和性能的好方法。特別地,您應該考慮使用線程來執行可以在后臺安全地完成且不需要用戶交互的處理。通過在后臺執行此類工作,可以使用戶能夠繼續使用應用程序,并且使應用程序的主用戶界面線程能夠維持應用程序的響應性。
適合于在單獨的線程上完成的處理包括:
? |
應用程序初始化。請在后臺線程上執行漫長的初始化,以便用戶能夠盡快地與您的應用程序交互,尤其是在應用程序功能的重要或主要部分并不依賴于該初始化完成時。 |
? |
遠程服務調用。請在單獨的后臺線程上通過網絡進行所有遠程調用。很難(如果不是無法)保證位于網絡上的服務的響應時間。在單獨的線程上執行這些調用可以減少發生網絡中斷或延遲的風險,從而避免對應用程序性能造成不利影響。 |
? |
IO 綁定處理。應該在單獨的線程上完成諸如在磁盤上搜索和排序數據之類的處理。通常,這種工作要受到磁盤 I/O 子系統而不是處理器可用性的限制,因此當該工作在后臺執行時,您的應用程序可以有效地維持其響應性。 |
盡管使用多個線程的性能好處可能很顯著,但需要注意,線程使用它們自己的資源,并且使用太多的線程可能給處理器(它需要管理線程之間的上下文切換)造成負擔。要避免這一點,請考慮使用線程池,而不是創建和管理您自己的線程。線程池將為您有效地管理線程,重新使用現有的線程對象,并且盡可能地減小與線程創建和處置相關聯的系統開銷。
如果用戶體驗受到后臺線程所執行的工作的影響,則您應該總是讓用戶了解工作的進度。以這種方式提供反饋可以增強用戶對您的應用程序的性能的感覺,并且防止他或她假設沒有任何事情發生。請努力確保用戶可以隨時取消漫長的操作。
您還應該考慮使用 Application 對象的 Idle 事件來執行簡單的操作。Idle 事件提供了使用單獨的線程來進行后臺處理的簡單替代方案。當應用程序不再有其他用戶界面消息需要處理并且將要進入空閑狀態時,該事件將激發。您可以通過該事件執行簡單的操作,并且利用用戶不活動的情況。例如:
[C#]
public Form1() { InitializeComponent(); Application.Idle += new EventHandler( OnApplicationIdle ); } private void OnApplicationIdle( object sender, EventArgs e ) { }
[Visual Basic .NET]
Public Class Form1 Inherits System.Windows.Forms.Form Public Sub New() MyBase.New() InitializeComponent() AddHandler Application.Idle, AddressOf OnApplicationIdle End Sub Private Sub OnApplicationIdle(ByVal sender As System.Object, ByVal e As System.EventArgs) End Sub End Class
注有關在智能客戶端中使用多個線程的詳細信息,請參閱第 6 章“使用多個線程”。
事務原則
事務可以提供重要的支持,以確保不會違反業務規則并維護數據一致性。事務可以確保一組相關任務作為一個單元成功或失敗。您可以使用事務來維護本地數據庫和其他資源(包括消息隊列的隊列)之間的一致性。
對于需要在網絡連接不可用時使用脫機緩存數據的智能客戶端應用程序,您應該將事務性數據排隊,并且在網絡連接可用時將其與服務器進行同步。
您應該避免使用涉及到位于網絡上的資源的分布式事務,因為這些情況可能導致與不斷變化的網絡和資源響應時間有關的性能問題。如果您的應用程序需要在事務中涉及到位于網絡上的資源,則應該考慮使用補償事務,以便使您的應用程序能夠在本地事務失敗時取消以前的請求。盡管補償事務在某些情況下可能不適用,但它們使您的應用程序能夠按照松耦合方式在事務的上下文內與網絡資源交互,從而減少了不在本地計算機控制之下的資源對應用程序的性能造成不利影響的可能性。
注有關在智能客戶端中使用事務的詳細信息,請參閱第 3 章“建立連接”。
優化應用程序啟動時間
快速的應用程序啟動時間幾乎可以使用戶立即開始與應用程序交互,從而使用戶立刻對應用程序的性能和可用性產生好感。
當應用程序啟動時,首先加載 CLR,再加載應用程序的主程序集,隨后加載為解析從應用程序的主窗體中引用的對象的類型所需要的所有程序集。CLR 在該階段不會 加載所有相關程序集;它僅加載包含主窗體類上的成員變量的類型定義的程序集。在加載了這些程序集之后,實時 (JIT) 編譯器將在方法運行時編譯方法的代碼(從 Main 方法開始)。同樣,JIT 編譯器不會 編譯您的程序集中的所有代碼。相反,將根據需要逐個方法地編譯代碼。
要盡可能減少應用程序的啟動時間,您應該遵循下列原則:
? |
盡可能減少應用程序主窗體類中的成員變量。這將在 CLR 加載主窗體類時盡可能減少必須解析的類型數量。 |
? |
盡量不要立即使用大型基類程序集(XML 庫或 ADO.NET 庫)中的類型。這些程序集的加載很費時間。使用應用程序配置類和跟蹤開關功能時將引入 XML 庫。如果要優先考慮應用程序啟動時間,請避免這一點。 |
? |
盡可能使用惰性加載。僅在需要時獲取數據,而不是提前加載和凍結 UI。 |
? |
將應用程序設計為使用較少的程序集。帶有大量程序集的應用程序會招致性能開銷增加。這些開銷來自加載元數據、訪問 CLR 中的預編譯映像中的各種內存頁以加載程序集(如果它是用本機映像生成器工具 Ngen.exe 預編譯的)、JIT 編譯時間、安全檢查等等。您應該考慮基于程序集的使用模式來合并程序集,以便降低相關聯的性能開銷。 |
? |
避免設計將多個組件的功能組合到一個組件中的單一類。將設計分解到多個只須在實際調用時進行編譯的較小類。 |
? |
將應用程序設計為在初始化期間對網絡服務進行并行調用。通過在初始化期間調用可以并行運行的網絡服務,可以利用服務代理提供的異步功能。這有助于釋放當前執行的線程并且并發地調用服務以完成任務。 |
? |
使用 NGEN.exe 編譯和試驗 NGen 和非 NGen 程序集,并且確定哪個程序集保存了最大數量的工作集頁面。NGEN.exe(它隨附在 .NET Framework 中)用于預編譯程序集以創建本機映像,該映像隨后被存儲在全局程序集緩存的特殊部分,以便應用程序下次需要它時使用。通過創建程序集的本機映像,可以使程序集更快地加載和執行,因為 CLR 不需要動態生成程序集中包含的代碼和數據結構。有關詳細信息,請參閱 Improving .NET Application Performance and Scalability 的第 5 章“Improving Managed Code Performance”中的“Working Set Considerations”和“NGen.exe Explained”部分,網址為:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag/html/scalenetchapt05.asp。 注如果您使用 NGEN 預編譯程序集,則會立即加載它的所有依賴程序集。 |
管理可用資源
公共語言運行庫 (CLR) 使用垃圾回收器來管理對象生存期和內存使用。這意味著無法再訪問的對象將被垃圾回收器自動回收,并且自動回收內存。由于多種原因無法再訪問對象。例如,可能沒有對該對象的任何引用,或者對該對象的所有引用可能來自其他可作為當前回收周期的一部分進行回收的對象。盡管自動垃圾回收使您的代碼不必負責管理對象刪除,但這意味著您的代碼不再對對象的確切刪除時間具有顯式控制。
請考慮下列原則,以確保您能夠有效地管理可用資源:
? |
確保在被調用方對象提供 Dispose 方法時該方法得到調用。如果您的代碼調用了支持 Dispose 方法的對象,則您應該確保在使用完該對象之后立即調用此方法。調用 Dispose 方法可以確保搶先釋放非托管資源,而不是等到發生垃圾回收。除了提供 Dispose 方法以外,某些對象還提供其他管理資源的方法,例如,Close 方法。在這些情況下,您應該參考文檔資料以了解如何使用其他方法。例如,對于 SqlConnection 對象而言,調用 Close 或 Dispose 都足可以搶先將數據庫連接釋放回連接池中。一種可以確保您在對象使用完畢之后立即調用 Dispose 的方法是使用 Visual C# .NET 中的 using 語句或 Visual Basic .NET 中的 Try/Finally 塊。 下面的代碼片段演示了 Dispose 的用法。 C# 中的 using 語句示例: using( StreamReader myFile = new StreamReader("C:\\ReadMe.Txt")){ string contents = myFile.ReadToEnd(); //... use the contents of the file } // dispose is called and the StreamReader's resources released Visual Basic .NET 中的 Try/Finally 塊示例: Dim myFile As StreamReader myFile = New StreamReader("C:\\ReadMe.Txt") Try String contents = myFile.ReadToEnd() '... use the contents of the file Finally myFile.Close() End Try 注在 C# 和 C++ 中,Finalize 方法是作為析構函數實現的。在 Visual Basic .NET 中,Finalize 方法是作為 Object 基類上的 Finalize 子例程的重寫實現的。 |
? |
如果您在客戶端調用過程中占據非托管資源,則請提供 Finalize 和 Dispose 方法。如果您在公共或受保護的方法調用中創建訪問非托管資源的對象,則應用程序需要控制非托管資源的生存期。在圖 8.1 中,第一種情況是對非托管資源的調用,在此將打開、獲取和關閉資源。在此情況下,您的對象無須提供 Finalize 和 Dispose 方法。在第二種情況下,在方法調用過程中占據非托管資源;因此,您的對象應該提供 Finalize 和 Dispose 方法,以便客戶端在使用完該對象后可以立即顯式釋放資源。 ![]() 圖 8.1:Dispose 和 Finalize 方法調用的用法 |
垃圾回收通常有利于提高總體性能,因為它將速度的重要性置于內存利用率之上。只有當內存資源不足時,才需要刪除對象;否則,將使用所有可用的應用程序資源以使您的應用程序受益。但是,如果您的對象保持對非托管資源(例如,窗口句柄、文件、GDI 對象和網絡連接)的引用,則程序員通過在這些資源不再使用時顯式釋放它們可以獲得更好的性能。如果您要在客戶端方法調用過程中占據非托管資源,則對象應該允許調用方使用 IDisposable 接口(它提供 Dispose 方法)顯式管理資源。通過實現 IDisposable,對象將通知它可被要求明確進行清理,而不是等待垃圾回收。實現 IDisposable 的對象的調用方在使用完該對象后將簡單地調用 Dispose 方法,以便它可以根據需要釋放資源。
有關如何在某個對象上實現 IDisposable 的詳細信息,請參閱 Improving .NET Application Performance and Scalability 中的第 5 章“Improving Managed Code Performance”,網址為:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag/html/scalenetchapt05.asp。
注如果您的可處置對象派生自另一個也實現了 IDisposable 接口的對象,則您應該調用基類的 Dispose 方法以使其可以清理它的資源。您還應該調用實現了 IDisposable 接口的對象所擁有的所有對象上的 Dispose。
Finalize 方法也使您的對象可以在刪除時顯式釋放其引用的任何資源。由于垃圾回收器所具有的非確定性,在某些情況下,Finalize 方法可能長時間不會被調用。實際上,如果您的應用程序在垃圾回收器刪除對象之前終止,則該方法可能永遠不會被調用。然而,需要使用 Finalize 方法作為一種后備策略,以防調用方沒有顯式調用 Dispose 方法(Dispose 和 Finalize 方法共享相同的資源清理代碼)。通過這種方式,可能在某個時刻釋放資源,即使這發生在最佳時刻之后。
注要確保 Dispose 和 Finalize 中的清理代碼不會被調用兩次,您應該調用 GC.SuppressFinalize 以通知垃圾回收器不要調用 Finalize 方法。
垃圾回收器實現了 Collect 方法,該方法強制垃圾回收器刪除所有對象掛起刪除。不應該從應用程序內調用該方法,因為回收周期在高優先級線程上運行。回收周期可能凍結所有 UI 線程,從而使得用戶界面停止響應。
有關詳細信息,請參閱 Improving .NET Application Performance and Scalability 中的“Garbage Collection Guidelines”、“Finalize and Dispose Guidelines”、“Dispose Pattern”和“Finalize and Dispose Guidelines”,網址為:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag/html/scalenetchapt05.asp。
優化 Windows 窗體性能
Windows 窗體為智能客戶端應用程序提供了內容豐富的用戶界面,并且您可以使用許多種技術來幫助確保 Windows 窗體提供最佳性能。在討論特定技術之前,對一些可以顯著提高 Windows 窗體性能的高級原則進行回顧是有用的。
? |
小心創建句柄。Windows 窗體將句柄創建虛擬化(即,它動態創建和重新創建窗口句柄對象)。創建句柄對象的系統開銷可能非常大;因此,請避免進行不必要的邊框樣式更改或者更改 MDI 父對象。 |
? |
避免創建帶有太多子控件的應用程序。Microsoft? Windows? 操作系統限制每個進程最多有 10,000 個控件,但您應該避免在窗體上使用成百上千個控件,因為每個控件都要消耗內存資源。 |
本節的其余部分討論您可以用來優化應用程序用戶界面性能的更為具體的技術。
使用 BeginUpdate 和 EndUpdate
許多 Windows 窗體控件(例如,ListView 和 TreeView 控件)實現了 BeginUpdate 和 EndUpdate 方法,它們在操縱基礎數據或控件屬性時取消了控件的重新繪制。通過使用 BeginUpdate 和 EndUpdate 方法,您可以對控件進行重大更改,并且避免在應用這些更改時讓控件經常重新繪制自身。此類重新繪制會導致性能顯著降低,并且用戶界面閃爍且不反應。
例如,如果您的應用程序具有一個要求添加大量節點項的樹控件,則您應該調用 BeginUpdate,添加所有必需的節點項,然后調用 EndUpdate。下面的代碼示例顯示了一個樹控件,該控件用于顯示許多個客戶的層次結構表示形式及其定單信息。
[C#]
// Suppress repainting the TreeView until all the objects have been created. TreeView1.BeginUpdate(); // Clear the TreeView. TreeView1.Nodes.Clear(); // Add a root TreeNode for each Customer object in the ArrayList. foreach( Customer customer2 in customerArray ) { TreeView1.Nodes.Add( new TreeNode( customer2.CustomerName ) ); // Add a child TreeNode for each Order object in the current Customer. foreach( Order order1 in customer2.CustomerOrders ) { TreeView1.Nodes[ customerArray.IndexOf(customer2) ].Nodes.Add( new TreeNode( customer2.CustomerName + "." + order1.OrderID ) ); } } // Begin repainting the TreeView. TreeView1.EndUpdate();
[Visual Basic .NET]
' Suppress repainting the TreeView until all the objects have been created. TreeView1.BeginUpdate() ' Clear the TreeView TreeView1.Nodes.Clear() ' Add a root TreeNode for each Customer object in the ArrayList For Each customer2 As Customer In customerArray TreeView1.Nodes.Add(New TreeNode(customer2.CustomerName)) ' Add a child TreeNode for each Order object in the current Customer. For Each order1 As Order In customer2.CustomerOrders TreeView1.Nodes(Array.IndexOf(customerArray, customer2)).Nodes.Add( _ New TreeNode(customer2.CustomerName & "." & order1.OrderID)) Next Next ' Begin repainting the TreeView. TreeView1.EndUpdate()
即使在您不希望向控件添加許多對象時,您也應該使用 BeginUpdate 和 EndUpdate 方法。在大多數情況下,您在運行之前將不知道要添加的項的確切個數。因此,為了妥善處理大量數據以及應付將來的要求,您應該總是調用 BeginUpdate 和 EndUpdate 方法。
注調用 Windows 窗體控件使用的許多 Collection 類的 AddRange 方法時,將自動為您調用 BeginUpdate 和 EndUpdate 方法。
使用 SuspendLayout 和 ResumeLayout
許多 Windows 窗體控件(例如,ListView 和 TreeView 控件)都實現了 SuspendLayout 和 ResumeLayout 方法,它們能夠防止控件在添加子控件時創建多個布局事件。
如果您的控件以編程方式添加和刪除子控件或者執行動態布局,則您應該調用 SuspendLayout 和 ResumeLayout 方法。通過 SuspendLayout 方法,可以在控件上執行多個操作,而不必為每個更改執行布局。例如,如果您調整控件的大小并移動控件,則每個操作都將引發單獨的布局事件。
這些方法按照與 BeginUpdate 和 EndUpdate 方法類似的方式操作,并且在性能和用戶界面穩定性方面提供相同的好處。
下面的示例以編程方式向父窗體中添加按鈕:
[C#]
private void AddButtons() { // Suspend the form layout and add two buttons. this.SuspendLayout(); Button buttonOK = new Button(); buttonOK.Location = new Point(10, 10); buttonOK.Size = new Size(75, 25); buttonOK.Text = "OK"; Button buttonCancel = new Button(); buttonCancel.Location = new Point(90, 10); buttonCancel.Size = new Size(75, 25); buttonCancel.Text = "Cancel"; this.Controls.AddRange(new Control[]{buttonOK, buttonCancel}); this.ResumeLayout(); }
[Visual Basic .NET]
Private Sub AddButtons() ' Suspend the form layout and add two buttons Me.SuspendLayout() Dim buttonOK As New Button buttonOK.Location = New Point(10, 10) buttonOK.Size = New Size(75, 25) buttonOK.Text = "OK" Dim buttonCancel As New Button buttonCancel.Location = New Point(90, 10) buttonCancel.Size = New Size(75, 25) buttonCancel.Text = "Cancel" Me.Controls.AddRange(New Control() { buttonOK, buttonCancel } ) Me.ResumeLayout() End Sub
每當您添加或刪除控件、執行子控件的自動布局或者設置任何影響控件布局的屬性(例如,大小、位置、定位點或停靠屬性)時,您都應該使用 SuspendLayout 和 ResumeLayout 方法。
處理圖像
如果您的應用程序顯示大量圖像文件(例如,.jpg 和 .gif 文件),則您可以通過以位圖格式預先呈現圖像來顯著改善顯示性能。
要使用該技術,請首先從文件中加載圖像,然后使用 PARGB 格式將其呈現為位圖。下面的代碼示例從磁盤中加載文件,然后使用該類將圖像呈現為預乘的、Alpha 混合 RGB 格式。例如:
[C#]
if ( image != null && image is Bitmap ) { Bitmap bm = (Bitmap)image; Bitmap newImage = new Bitmap( bm.Width, bm.Height, System.Drawing.Imaging.PixelFormat.Format32bppPArgb ); using ( Graphics g = Graphics.FromImage( newImage ) ) { g.DrawImage( bm, new Rectangle( 0,0, bm.Width, bm.Height ) ); } image = newImage; }
[Visual Basic .NET]
If Not(image Is Nothing) AndAlso (TypeOf image Is Bitmap) Then Dim bm As Bitmap = CType(image, Bitmap) Dim newImage As New Bitmap(bm.Width, bm.Height, _ System.Drawing.Imaging.PixelFormat.Format32bppPArgb) Using g As Graphics = Graphics.FromImage(newImage) g.DrawImage(bm, New Rectangle(0, 0, bm.Width, bm.Height)) End Using image = newImage End If
使用分頁和惰性加載
在大多數情況下,您應該僅在需要時檢索或顯示數據。如果您的應用程序需要檢索和顯示大量信息,則您應該考慮將數據分解到多個頁面中,并且一次顯示一頁數據。這可以使用戶界面具有更高的性能,因為它無須顯示大量數據。此外,這可以提高應用程序的可用性,因為用戶不會同時面對大量數據,并且可以更加容易地導航以查找他或她需要的確切數據。
例如,如果您的應用程序顯示來自大型產品目錄的產品數據,則您可以按照字母順序顯示這些項,并且將所有以“A”開頭的產品顯示在一個頁面上,將所有以“B”開頭的產品顯示在下一個頁面上。然后,您可以讓用戶直接導航到適當的頁面,以便他或她無須瀏覽所有頁面就可以獲得他或她需要的數據。
以這種方式將數據分頁還使您可以根據需要獲取后臺的數據。例如,您可能只需要獲取第一頁信息以便顯示并且讓用戶與其進行交互。然后,您可以獲取后臺中的、已經準備好供用戶使用的下一頁數據。該技術在與數據緩存技術結合使用時可能特別有效。
您還可以通過使用惰性加載技術來提高智能客戶端應用程序的性能。您無須立即加載可能在將來某個時刻需要的數據或資源,而是可以根據需要加載它們。您可以在構建大型列表或樹結構時使用惰性加載來提高用戶界面的性能。在此情況下,您可以在用戶需要看到數據時(例如,在用戶展開樹節點時)加載它。
優化顯示速度
根據您用于顯示用戶界面控件和應用程序窗體的技術,您可以用多種不同的方式來優化應用程序的顯示速度。
當您的應用程序啟動時,您應該考慮盡可能地顯示簡單的用戶界面。這將減少啟動時間,并且向用戶呈現整潔且易于使用的用戶界面。而且,您應該努力避免引用類以及在啟動時加載任何不會立刻需要的數據。這將減少應用程序和 .NET Framework 初始化時間,并且提高應用程序的顯示速度。
當您需要顯示對話框或窗體時,您應該在它們做好顯示準備之前使其保持隱藏狀態,以便減少需要的繪制工作量。這將有助于確保窗體僅在初始化之后顯示。
如果您的應用程序具有的控件含有覆蓋整個客戶端表面區域的子控件,則您應該考慮將控件背景樣式設置為不透明。這可以避免在發生每個繪制事件時重繪控件的背景。您可以通過使用 SetStyle 方法來設置控件的樣式。使用 ControlsStyles.Opaque 枚舉可以指定不透明控件樣式。
您應該避免任何不必要的控件重新繪制操作。一種方法是在設置控件的屬性時隱藏控件。在 OnPaint 事件中具有復雜繪圖代碼的應用程序能夠只重繪窗體的無效區域,而不是繪制整個窗體。OnPaint 事件的 PaintEventArgs 參數包含一個 ClipRect 結構,它指示窗口的哪個部分無效。這可以減少用戶等待查看完整顯示的時間。
使用標準的繪圖優化,例如,剪輯、雙緩沖和 ClipRectangle。這還將通過防止對不可見或要求重繪的顯示部分執行不必要的繪制操作,從而有助于改善智能客戶端應用程序的顯示性能。有關增強繪圖性能的詳細信息,請參閱 Painting techniques using Windows Forms for the Microsoft .NET Framework,網址為:http://windowsforms.net/articles/windowsformspainting.aspx。
如果您的顯示包含動畫或者經常更改某個顯示元素,則您應該使用雙緩沖或多緩沖,在繪制當前圖像的過程中準備下一個圖像。System.Windows.Forms 命名空間中的 ControlStyles 枚舉適用于許多控件,并且 DoubleBuffer 成員可以幫助防止閃爍。啟用 DoubleBuffer 樣式將使您的控件繪制在離屏緩沖中完成,然后同時繪制到屏幕上。盡管這有助于防止閃爍,但它的確為分配的緩沖區使用了更多內存。
性能調整和診斷
在設計和實現階段處理性能問題是實現應用程序性能目標的最劃算的方法。但是,您只有在開發階段經常且盡早測試應用程序的性能,才能真正有效地優化應用程序的性能。
盡管針對性能進行設計和測試都很重要,但在這些早期階段優化每個組件和所有代碼不是有效的資源用法,因此應該予以避免。所以,應用程序可能存在您在設計階段未預料到的性能問題。例如,您可能遇到由于兩個系統或組件之間的無法預料的交互而產生的性能問題,或者您可能使用原來存在的、未按希望的方式執行的代碼。在此情況下,您需要追究性能問題的根源,以便您可以適當地解決該問題。
本節討論一些將幫助您診斷性能問題以及調整應用程序以獲得最佳性能的工具和技術。
制定性能目標
當您設計和規劃智能客戶端應用程序時,您應該仔細考慮性能方面的要求,并且定義合適的性能目標。在定義這些目標時,請考慮您將如何度量應用程序的實際性能。您的性能度量標準應該明確體現應用程序的重要性能特征。請努力避免無法準確度量的模糊或不完整的目標,例如,“應用程序必須快速運行”或“應用程序必須快速加載”。您需要了解應用程序的性能和可伸縮性目標,以便您可以設法滿足這些目標并且圍繞它們來規劃您的測試。請確保您的目標是可度量的和可驗證的。
定義良好的性能度量標準使您可以準確跟蹤應用程序的性能,以便您可以確定應用程序是否能夠滿足它的性能目標。這些度量標準應該包括在應用程序測試計劃中,以便可以在應用程序的測試階段度量它們。
本節重點討論與智能客戶端應用程序相關的特定性能目標的定義。如果您還要設計和生成客戶端應用程序將消耗的網絡服務,則您還需要為這些服務定義適當的性能目標。在此情況下,您應該確保考慮整個系統的性能要求,以及應用程序各個部分的性能與其他部分以及整個系統之間存在怎樣的關系。
考慮用戶的觀點
當您為智能客戶端應用程序確定合適的性能目標時,您應該仔細考慮用戶的觀點。對于智能客戶端應用程序而言,性能與可用性和用戶感受有關。例如,只要用戶能夠繼續工作并且獲得有關操作進度的足夠反饋,用戶就可以接受漫長的操作。
在確定要求時,將應用程序的功能分解為多個使用情景或使用案例通常是有用的。您應該識別對于實現特定性能目標而言關鍵且必需的使用案例和情景。應該將許多使用案例所共有且經常執行的任務設計得具有較高性能。同樣,如果任務要求用戶全神貫注并且不允許用戶從其切換以執行其他任務,則需要提供優化的且有效的用戶體驗。如果任務不太經常使用且不會阻止用戶執行其他任務,則可能無須進行大量調整。
對于您識別的每個性能敏感型任務,您都應該精確地定義用戶的操作以及應用程序的響應方式。您還應該確定每個任務使用的網絡和客戶端資源或組件。該信息將影響性能目標,并且將驅動對性能進行度量的測試。
可用性研究提供了非常有價值的信息源,并且可能大大影響性能目標的定義。正式的可用性研究在確定用戶如何執行他們的工作、哪些使用情景是共有的以及哪些不是共有的、用戶經常執行哪些任務以及從性能觀點看來應用程序的哪些特征是重要的等方面可能非常有用。如果您要生成新的應用程序,您應該考慮提供應用程序的原型或模型,以便可以執行基本的可用性測試。
考慮應用程序操作環境
對應用程序的操作環境進行評估是很重要的,因為這可能對應用程序施加必須在您制定的性能目標中予以反映的約束。
位于網絡上的服務可能對您的應用程序施加性能約束。例如,您可能需要與您無法控制的 Web 服務進行交互。在這種情況下,需要確定該服務的性能,并且確定這是否將對客戶端應用程序的性能產生影響。
您還應該確定任何相關服務和組件的性能如何隨著時間的變化而變化。某些系統會經受相當穩定的使用,而其他系統則會在一天或一周的特定時間經受變動極大的使用。這些區別可能在關鍵時間對應用程序的性能造成不利影響。例如,提供應用程序部署和更新服務的服務可能會在星期一早上 9 點緩慢響應,因為所有用戶都在此時升級到應用程序的最新版本。
另外,還需要準確地對所有相關系統和組件的性能進行建模,以便可以在嚴格模擬應用程序的實際部署環境的環境中測試您的應用程序。對于每個系統,您都應該確定性能概況以及最低、平均和最高性能特征。然后,您可以在定義應用程序的性能要求時根據需要使用該數據。
您還應該仔細考慮用于運行應用程序的硬件。您將需要確定在處理器、內存、圖形功能等方面的目標硬件配置,或者至少確定一個如果得不到滿足則無法保證性能的最低配置。
通常,應用程序的業務操作環境將規定一些更為苛刻的性能要求。例如,執行實時股票交易的應用程序將需要執行這些交易并及時顯示所有相關數據。
性能調整過程
對應用程序進行性能調整是一個迭代過程。該過程由一些重復執行直至應用程序滿足其性能目標的階段組成。(請參見圖 8.2。)

圖 8.2:性能調整過程
正如圖 8.2 所闡明的,性能調整要求您完成下列過程:
? |
建立基準。在您開始針對性能調整應用程序時,您必須具有與性能目標、目標和度量標準有關的定義良好的基準。這可能包括應用程序工作集大小、加載數據(例如,目錄)的時間、事務持續時間等等。 |
? |
收集數據。您將需要通過針對您已經定義的性能目標度量應用程序的性能,來對應用程序性能進行評價。性能目標應該體現特定的且可度量的度量標準,以使您可以在任何時刻量化應用程序的性能。要使您可以收集性能數據,您可能必須對應用程序進行規范,以便可以發布和收集必需的性能數據。下一節將詳細討論您可以用來完成這一工作的一些選項。 |
? |
分析結果。在收集應用程序的性能數據之后,您將能夠通過確定哪些應用程序功能要求最多的關注,來區分性能調整工作的輕重緩急。此外,您可以使用該數據來確定任何性能瓶頸的位置。通常,您將只能夠通過收集更詳細的性能數據來確定瓶頸的確切位置:例如,通過使用應用程序規范。性能分析工具可能幫助您識別瓶頸。 |
? |
調整應用程序。在已經識別瓶頸之后,您可能需要修改應用程序或其配置,以便嘗試解決問題。您應該致力于將更改降低至最低限度,以便可以確定更改對應用程序性能的影響。如果您同時進行多項更改,可能難以確定每項更改對應用程序的總體性能的影響。 |
? |
測試和度量。在更改應用程序或其配置之后,您應該再次測試它以確定更改具有的效果,并且使新的性能數據得以收集。性能工作通常要求進行體系結構或其他具有較高影響的更改,因此徹底的測試是很關鍵的。您的應用程序測試計劃應該針對預料到的所有情況,在配置了適當硬件和軟件的客戶計算機上演習應用程序所實現的完整范圍的功能。如果您的應用程序使用網絡資源,則應該加載這些資源,以便您可以獲得有關應用程序在此類環境中所具有的性能的準確度量。 |
上述過程將使您可以通過針對特定目標度量應用程序的總體性能,來重點解決特定的性能問題。
性能工具
您可以使用許多工具來幫助您收集和分析應用程序的性能數據。本節中介紹的每種工具都具有不同的功能,您可以使用這些功能來度量、分析和查找應用程序中的性能瓶頸。
注除了這里介紹的工具以外,您還可以使用其他一些選項和第三方工具。有關其他日志記錄和異常管理選項的說明,請參閱Exception Management Architecture Guide,網址為:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnbda/html/exceptdotnet.asp
在決定哪些工具最適合您的需要之前,您應該仔細考慮您的確切要求。
使用性能日志和警報
性能日志和警報是作為 Windows 操作系統的一部分發行的一種管理性能監控工具。它依靠由各種 Windows 組件、子系統和應用程序發布的性能計數器,使您可以跟蹤資源使用情況以及針對時間以圖形方式繪制它們。
您可以使用 Performance Logs and Alerts 來監控標準的性能計數器(例如,內存使用情況或處理器使用情況),或者您可以定義您自己的自定義計數器來監控應用程序特定的活動。
.NET CLR 提供了許多有用的性能計數器,它們使您可以洞察應用程序性能的好壞。關系比較大的一些性能對象是:
? |
.NET CLR 內存。提供有關托管 .NET 應用程序內存使用情況的數據,包括應用程序正在使用的內存數量以及對未使用的對象進行垃圾回收所花費的時間。 |
? |
.NET CLR 加載。提供有關應用程序正在使用的類和應用程序域的數量的數據,并且提供有關它們的加載和卸載速率的數據。 |
? |
.NET CLR 鎖和線程。提供與應用程序內使用的線程有關的性能數據,包括線程個數以及試圖同時對受保護的資源進行訪問的線程之間的爭用率。 |
? |
.NET CLR 網絡。提供與通過網絡發送和接收數據有關的性能計數器,包括每秒發送和接收的字節數以及活動連接的個數。 |
? |
.NET CLR 異常。提供有關應用程序所引發和捕獲的異常個數的報告。 |
有關上述計數器、它們的閾值、要度量的內容以及如何度量它們的詳細信息,請參閱 Improving .NET Application Performance and Scalability 的第 15 章“Measuring .NET Application Performance”中的“CLR and Managed Code”部分,網址為:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag/html/scalenetchapt15.asp。
您的應用程序還可以提供您可以通過使用性能日志和警報輕松監控的、應用程序特定的性能計數器。您可以像以下示例所顯示的那樣,定義自定義性能計數器:
[C#]
PerformanceCounter counter = new PerformanceCounter( "Category", "CounterName", false );
[Visual Basic .NET]
Dim counter As New PerformanceCounter("Category", "CounterName", False)
在創建性能計數器對象之后,您可以為您的自定義性能計數器指定類別,并將所有相關計數器保存在一起。PerformanceCounter 類在 System.Diagnostics 命名空間中定義,該命名空間中還定義了其他一些可用于讀取和定義性能計數器和類別的類。有關創建自定義性能計數器的詳細信息,請參閱知識庫中編號為 317679 的文章“How to create and make changes to a custom counter for the Windows Performance Monitor by using Visual Basic .NET”,網址為:http://support.microsoft.com/default.aspx?scid=kb;en-us;317679。
注要注冊性能計數器,您必須首先注冊該類別。您必須具有足夠的權限才能注冊性能計數器類別(它可能影響您部署應用程序的方式)。
規范
您可以使用許多工具和技術來幫助您對應用程序進行規范,并且生成度量應用程序性能所需的信息。這些工具和技術包括:
? |
Event Tracing for Windows (ETW)。該 ETW 子系統提供了一種系統開銷較低(與性能日志和警報相比)的手段,用以監控具有負載的系統的性能。這主要用于必須頻繁記錄事件、錯誤、警告或審核的服務器應用程序。有關詳細信息,請參閱 Microsoft Platform SDK 中的“Event Tracing”,網址為:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/perfmon/base/event_tracing.asp。 |
? |
Enterprise Instrumentation Framework (EIF)。EIF 是一種可擴展且可配置的框架,您可以使用它來對智能客戶端應用程序進行規劃。它提供了一種可擴展的事件架構和統一的 API — 它使用 Windows 中內置的現有事件、日志記錄和跟蹤機制,包括 Windows Management Instrumentation (WMI)、Windows Event Log 和 Windows Event Tracing。它大大簡化了發布應用程序事件所需的編碼。如果您計劃使用 EIF,則需要通過使用 EIF .msi 在客戶計算機上安裝 EIF。如果您要在智能客戶端應用程序中使用 EIF,則需要在決定應用程序的部署方式時考慮這一要求。有關詳細信息,請參閱“How To:Use EIF”,網址為:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag/html/scalenethowto14.asp。 |
? |
Logging Application Block。Logging Application Block 提供了可擴展且可重用的代碼組件,以幫助您生成規范化的應用程序。它建立在 EIF 的功能基礎之上,以提供某些功能,例如,針對事件架構的增強功能、多個日志級別、附加的事件接收等等。有關詳細信息,請參閱“Logging Application Block”,網址為“http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag/html/Logging.asp。 |
? |
Windows Management Instrumentation (WMI)。WMI 組件是 Windows 操作系統的一部分,并且提供了用于訪問企業中的管理信息和控件的編程接口。系統管理員常用它來自動完成管理任務(通過使用調用 WMI 組件的腳本)。有關詳細信息,請參閱 Windows Management Information,網址為:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/wmi_start_page.asp。 |
? |
調試和跟蹤類。.NET Framework 在 System.Diagnosis 下提供了 Debug 和 Trace 類來對代碼進行規范。Debug 類主要用于打印調試信息以及檢查是否有斷言。Trace 類使您可以對發布版本進行規范,以便在運行時監控應用程序的完好狀況。在 Visual Studio .NET 中,默認情況下啟用跟蹤。在使用命令行版本時,您必須為編譯器添加 /d:Trace 標志,或者在 Visual C# .NET 源代碼中添加 #define TRACE,以便啟用跟蹤。對于 Visual Basic .NET 源代碼,您必須為命令行編譯器添加 /d:TRACE=True。有關詳細信息,請參閱知識庫中編號為 815788 的文章“HOW TO:Trace and Debug in Visual C# .NET”,網址為:http://support.microsoft.com/default.aspx?scid=kb;en-us;815788。 |
CLR Profiler
CLR Profiler 是 Microsoft 提供的一種內存分析工具,并且可以從 MSDN 下載。它使您能夠查看應用程序進程的托管堆以及調查垃圾回收器的行為。使用該工具,您可以獲取有關應用程序的執行、內存分配和內存消耗的有用信息。這些信息可以幫助您了解應用程序的內存使用方式以及如何優化應用程序的內存使用情況。
CLR Profiler 可從 http://msdn.microsoft.com/netframework/downloads/tools/default.aspx 獲得。有關如何使用 CLR Profiler 工具的詳細信息,另請參閱“How to use CLR Profiler”,網址為:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag/html/scalenethowto13.asp?frame=true。
CLR Profiler 在日志文件中記錄內存消耗和垃圾回收器行為信息。然后,您可以使用一些不同的圖形視圖,通過 CLR Profiler 來分析該數據。一些比較重要的視圖是:
? |
Allocation Graph。顯示有關對象分配方式的調用堆棧。您可以使用該視圖來查看方法進行的每個分配的系統開銷,隔離您不希望發生的分配,以及查看方法可能進行的過度分配。 |
? |
Assembly, Module, Function, and Class Graph。顯示哪些方法造成了哪些程序集、函數、模塊或類的加載。 |
? |
Call Graph。使您可以查看哪些方法調用了其他哪些方法以及相應的調用頻率。您可以使用該圖表來確定庫調用的系統開銷,以及調用了哪些方法或對特定方法進行了多少個調用。 |
? |
Time Line。提供了有關應用程序執行的基于文本的、按時間順序的層次結構視圖。使用該視圖可以查看分配了哪些類型以及這些類型的大小。您還可以使用該視圖查看方法調用使得哪些程序集被加載,并且分析您不希望發生的分配。您可以分析完成器的使用情況,并且識別尚未實現或調用 Close 或 Dispose 從而導致瓶頸的方法。 |
您可以使用 CLR Profiler.exe 來識別和隔離與垃圾回收有關的問題。這包括內存消耗問題(例如,過度或未知的分配、內存泄漏、生存期很長的對象)以及在執行垃圾回收時花費的時間的百分比。
注有關如何使用 CLR Profiler 工具的詳細信息,請參閱“Improving .NET Application Performance and Scalability”,網址為:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag/html/scalenethowto13.asp?frame=true。
小結
要完全實現智能客戶端應用程序的潛能,您需要在應用程序的設計階段仔細考慮性能問題。通過在早期階段解決這些性能問題,您可以在應用程序設計過程中控制成本,并減小在開發周期的后期陷入性能問題的可能性。
本章分析了許多不同的技術,您可以在規劃和設計智能客戶端應用程序時使用這些技術,以確保優化它們的性能。本章還考察了您可以用來確定智能客戶端應用程序內的性能問題的一些工具和技術。
參考資料
有關詳細信息,請參閱以下內容:
? | |
? | |
? | |
? | |
? | |
? |
http://msdn.microsoft.com/msdnmag/issues/02/08/AdvancedBasics/default.aspx |
? |
http://msdn.microsoft.com/library/default.asp?url=/msdnmag/issues/04/01/NET/toc.asp?frame=true |
? |