本指南將示範如何透過兩種主要方式提升 Windows 應用程式的效能:
減少記憶體使用量
有多種方法可以減少 Windows 應用程式所佔用的記憶體,你可以:
- 減少前景記憶體使用量
- 減少背景工作
- 在背景中釋放資源
- 確保你的應用程式不會洩漏記憶體
為了適當地減少記憶體使用,首先要了解:
- 記憶體的使用與分配,使用 工作集、動態記憶體與虛擬分配,
- 如何 捕捉系統跡錄,以及
- 如何分析系統追蹤?
一旦您有系統追蹤可分析,我們將建議如何 應用追蹤分析以降低記憶體使用。
工作集、動態記憶體與虛擬分配
應用程式的工作 集 ——即其虛擬位址空間中目前駐留於記憶體中的頁面集合——是衡量應用程式記憶體使用情況的一種指標。
應用程式使用的記憶體量會影響其執行時的效能,以及系統整體的反應速度。 將記憶體使用量降至最低能幫助應用程式提高效能,因為這樣可以減少與存取較多記憶體相關的 CPU 成本。 較低的記憶體使用也有助於系統反應速度,以及應用程式使用者整體體驗,因為應用程式不會取代其他記憶體內容。
記憶體位移可能發生在系統嘗試保留最近存取的記憶體內容,必要時會修剪或分頁先前使用的內容。 當使用者切換回命令行界面或其他應用程式,且所需資料不在記憶體中時,資料必須從磁碟讀取。 使用者很可能會注意到這個過程會變慢。
應用程式所使用的記憶體有兩個關鍵部分:1)動態記憶體,2)檔案備份記憶體。 檔案後備記憶體使用來自應用程式使用的二進位檔與資料檔案,例如資料庫。 這通常不是應用程式記憶體使用中的重要部分,且通常是常數。 (例外情況包括資料處理應用程式、程式碼編譯等。) 記憶體使用量較重要的來源及洩漏發生的來源是動態記憶體。
動態記憶體對應於應用程式使用 記憶體配置例程所分配的虛擬記憶體。 與檔案備份記憶體不同,後者會在系統重啟後持續存在,動態記憶體僅存在於應用程式的整個生命週期。 動態記憶體是記憶體使用中常見的重要來源,也是記憶體洩漏的表現來源。
虛擬配置例程 (VirtualAlloc)處理來自 Windows 應用程式的記憶體分配請求,獨立於用於記憶體分配的應用層例程。 雖然應用程式分配的記憶體不一定全部都駐留在記憶體中,但分析這些配置能提供一種一致的方式來理解應用程式的記憶體使用情況。
為了了解應用程式的記憶體使用情況並尋找改進之處,我們建議按照下方說明擷取 VirtualAllocation 跟蹤。
擷取系統追蹤以分析記憶體使用情況
記錄裝置活動在一段時間內稱為 系統追蹤。 系統追蹤會產生一個追蹤檔案,可用來產生報告,並協助你找出如何提升應用程式效能的方法。
痕跡長度可有所不同:
- 短的執行追蹤可以用來捕捉應用程式的啟動。 這可能包括應用程式轉換到非活動狀態,應用程式視窗會被最小化或關閉,而應用程式程序仍在進行。
- 長時間的追蹤,通常持續數分鐘,有助於診斷記憶體洩漏。 如果記憶體使用量隨時間持續上升,通常暗示有洩漏。
有多種工具可用於監控記憶體使用,包括:
本文將專注於使用 Windows 效能分析器。 想了解更多關於選擇用於分析應用程式效能的工具,請參閱 「在 Visual Studio 效能分析器、Windows 效能工具包與 PerfView 之間選擇」。
捕捉痕跡:
在管理員模式下開啟命令列(PowerShell 或命令提示字元)。 (若未以管理員模式執行,可能會收到錯誤代碼:0xc5585011,「未能啟用系統效能剖析政策。」)
輸入指令:
wpr -start VirtualAllocation -filemode執行你正在調查的情境。 (例如啟動你的應用程式。)
輸入指令:
wpr -stop Trace.etl
分析系統追蹤紀錄
為了找出應用程式中哪些功能分配了記憶體你可以減少,你現在需要分析被捕捉到的系統追蹤。 分析痕跡:
使用 Windows效能分析器開啟追蹤,輸入以下指令:
wpa.exe Trace.etl在
圖形瀏覽器視窗 中,展開記憶體 區塊,按右鍵點擊「總提交」圖表,選擇 「新增圖表至新分析視圖」 。點擊設定齒輪並選擇以下欄位排列:程序、提交類型、提交堆疊與大小,開啟檢視編輯器。
點擊 Size 欄標題,結果會依降減排序。 Commit Stack 顯示分配記憶體的程式碼路徑。 這些結果有助於理解分配的原因。 依尺寸排序讓你能專注於較大的分配,並調查是否有優化的機會。
透過右鍵點擊程序並選擇篩選至所選項目,篩選出你有興趣分析的程序。
要在視窗中放大你感興趣的區域,選擇一個範圍,右鍵點擊圖表,然後選擇 縮放。
瀏覽提交堆疊,了解哪些函式已分配記憶體。 提交堆疊需要 載入符號。 要載入符號,請從上方導覽選單欄選擇「Trace>Load symbols」。
應用你的追蹤分析以降低記憶體使用量
在分析分配的記憶體時,你會發現一些線索,幫助你判斷哪些地方可以減少記憶體使用。
關於運用追蹤分析來更新程式碼以減少記憶體使用,有幾個方面需要考慮:
在前景時減少記憶體使用:分析記憶體追蹤有助於你找出前景中不必要的記憶體使用,並更新程式碼以減少或移除這些使用。
在背景執行時降低工作負荷:系統有政策會將頁面從程序工作集中排除。 在背景使用較少的記憶體,能讓系統透過減少應用程式記憶體的佔用量來提高效率。 了解如何 透過減少背景工作來提升功耗與電池續航,這也將轉化為在背景使用時的記憶體使用量減少。
在背景釋放資源:在執行時,應用程式可能會建立一些記憶體快取,並建立圖形配置以支援其使用者介面。 當應用程式最小化或不可見時,這些分配可能會被釋放。 應用程式可以註冊低記憶體通知以執行此類行動,但更好的策略可能是在一段時間未使用後,當應用程式認定自己為非活動時,釋放記憶體。 這段停用時間因使用方式而異,因此可能顯示的非活躍使用時間從幾分鐘到半小時甚至更久不等。 在節省記憶體與回應速度之間,應該謹慎平衡。 如果快取重建成本高昂,應用程式可以選擇在應用程式生命週期內保留該快取。
確保應用程式不會洩漏記憶體:要檢查記憶體洩漏,首先建立一個穩態基準測試,讓應用程式的記憶體使用量達到停滯或不超過某個數值。 你可以透過持續使用應用程式或讓它在背景閒置來建立這種穩定狀態。 利用你捕捉到的痕跡來識別可能的記憶體洩漏,你可以找出該記憶體在程式碼中被分配的位置,以及它完成任務後如何被解除使用。 如果記憶體在應用程式執行時持續成長,這很可能是記憶體洩漏的徵兆。 放大與你追蹤中成長區域相對應的區域,仔細分析提交堆疊。
有效利用磁碟空間
磁碟容量 是指應用程式在非活動狀態(非執行程式碼)時的大小。 如果應用程式佔用大量磁碟空間,這就是一個優化的機會。
減少應用程式磁碟佔用量有幾種方法可以提升效能:
當磁碟滿了,檔案系統就無法連續地儲存新內容。 完整的磁碟會變得碎片化,將新內容儲存在非連續的扇區上。 這代表從磁碟存取該內容時,延遲時間會變長。 當磁碟上的內容是連續的並且可以依序存取或透過較大的 IO 操作讀取時,IO 系統將提供更佳的磁碟數據吞吐量。
對於基於 SSD 的系統來說,滿磁碟可能代表較長的寫入延遲。 當可用來吸收寫入的空格較少時,寫入可能會觸發讀取-修改-寫入操作,導致效能變慢。
滿硬碟可能會阻礙更新應用程式的能力。 雖然作業系統具備韌性,能讓系統保持最新且安全,即使磁碟空間有限,若有充足的磁碟空間用於應用程式更新,將帶來更快、更順暢的更新體驗。
執行時需要大量磁碟空間存取,也會影響記憶體使用。 這會影響你的應用程式和整個系統的反應速度。 此外,若執行時僅需少量磁碟佔地,應用程式可能無法有效利用磁碟空間。
減少或更有效率使用磁碟空間的幾種方法包括:
對磁碟空間套用「付費遊戲」原則(只下載你需要的部分):應用程式可能包含廣泛的功能,但並非所有功能都適用於所有使用者。 這可能是硬碟佔用面積較大的原因之一。 透過「付費遊玩」原則,你可以要求用戶只選擇下載他們需要的功能,這樣下載應用程式時磁碟空間就會更小。 額外內容僅在使用者需要更豐富功能時可選下載。 除了功能外,你也可以將相同的「付費遊玩」原則套用到語言支援上。 應用程式預設可包含部分熱門語言選項,並可選擇性地加入或依使用者系統中設定的地點加入更多語言。
有效調整快取大小:在某些情況下,應用程式可以使用磁碟快取來提升使用者體驗的反應速度。 可以設定應用程式如何管理快取的政策,並根據磁碟容量設定快取大小上限,並在磁碟空間不足時調整快取大小。
有效運用資產:應用程式通常會包含影像素材,並可能包含多種影像尺寸以支援多種解析度。 針對部分解析度優化影像大小、尺寸、格式與壓縮,並利用縮放支援剩餘解析度,能大幅減少磁碟佔用空間。
探索二進位優化機會:像 SizeBench 這類工具,讓應用程式作者能調查造成二進位佔用的因素,並尋找減少磁碟空間使用的機會。