在 Windows 上正確比較程式各版本速度的方法

· 更新日期: · · Windows, Benchmark, Performance, Profiling, Power Management

更新紀錄(2 筆,最後更新 2026年09月04日)

本文的修改紀錄。已保存的更新前版本,可透過附有 DOI 的永久連結閱讀。

已將繁體中文版改寫為日文原文的完整翻譯。先前的繁體中文版只譯出日文原文的一部分,遺漏了章節、表格、Mermaid 圖、圖說與 FAQ。本次依日文原文將這些內容全部補回,並新增本文的知識地圖章節。技術主張與日文版一致。 查看更新前的版本 (DOI: 10.5281/zenodo.22279410)
補上了日文原文中已有的諮詢引導(consultation_services)。內文沒有改動。 查看更新前的版本 (DOI: 10.5281/zenodo.21616294)
初次發布
引用本文(DOI: 10.5281/zenodo.21616293)

本文保存於 Zenodo。以下同時提供一律指向最新版本的 DOI,以及固定於您正在閱讀版本的 DOI。

Go Komura(2026)。〈在 Windows 上正確比較程式各版本速度的方法〉。小村軟體有限公司。https://doi.org/10.5281/zenodo.21616293 https://comcomponent.com/zh-TW/blog/2026/03/16/002-windows-benchmark-comparing-program-versions/

DOI(最新版本)
10.5281/zenodo.21616293
DOI(此版本)
10.5281/zenodo.22297134

想在 Windows 上比較程式的 A 版與 B 版。 這時最不該做的,就是在同一台電腦上各跑 1 次,然後說「感覺 B 快 8%」。

那 8% 也許真的是程式碼的差異。 但在 Windows 的基準測試裡,更常見的情況是:真正的原因其實是 Power mode(電源模式)、Power plan(電源計劃)、溫度、背景更新、搜尋索引、病毒掃描、親和性、執行順序、快取狀態 其中之一。接下來要做的,是把條件一個一個排除掉的瑣碎工作。

「感覺快 8%」的真面目說明各跑一次得到的差異也許是程式碼差異,但常常其實是電源、溫度、背景活動或快取其中之一,因此需要把條件一個一個排除的圖。也許是常見的真面目各跑 1 次來比較得到「感覺快 8%」真的是程式碼差異電源、溫度、雜訊、快取把條件一個一個排除

圖 1: 只跑 1 次得到的差異未必是程式碼差異,要先排除條件才能下定論。

本文梳理在 Windows 上比較不同版本程式執行速度的做法,目標是 盡量貼近程式碼本身的差異。 主要以 Windows 11 為對象,但 powercfg、start 等指令大部分在 Windows 10 上同樣可用。

先掌握的術語

本文中有些術語會直接以英文出現。為了避免第一次看到就卡住,先在這裡整理起來。

術語 意義
ETW Event Tracing for Windows。Windows 內建的追蹤基礎架構,可以把 OS、驅動程式與應用程式送出的事件一起記錄下來
WPR / WPA Windows Performance Recorder 與 Windows Performance Analyzer。前者是記錄 ETW 追蹤的工具,後者是開啟追蹤並加以分析的工具,兩者都包含在 Windows ADK 中
clean boot 停用 Microsoft 以外的服務與啟動應用程式,以最精簡的設定啟動的步驟(全新啟動)。目的是減少常駐應用程式帶來的雜訊
PGO Profile-Guided Optimization。先執行一次收集分支與呼叫的統計,再把這些統計用在下一次建置的最佳化判斷上。它會改變建置條件,因此是檢查比較對象是否對齊時的項目之一
p95 / p99 百分位數。把所有 run 由快到慢排列後,位於第 95% / 99% 位置的值。「每 20 次會有 1 次比這個更慢」就是 p95
NUMA Non-Uniform Memory Access。從 CPU 看過去,到記憶體的距離並不一致的架構。在哪個節點上執行,記憶體存取的速度就會不同
core parking(核心停駐) 負載較低時,讓用不到的邏輯處理器休息的電源管理機制

先講結論

要提高重現性,歸結起來就是下面 6 點。

  1. 先決定「要比較什麼」 想看的是程式碼差異,還是真實使用者的體感,該對齊的環境並不相同。

  2. 把 Power mode(電源模式)與 Power plan(電源計劃)當成兩件不同的事來記錄 在 Windows 上如果這裡處理得草率,比較很容易變成在比 OS 的省電策略。

  3. 把冷機的第 1 次與熱機後的穩態分開 只有第一次特別快、只有後半特別慢,都不算罕見。

  4. 以 A→B→A→B 的方式交替執行 先把 A 全部跑完再跑 B,溫度與背景狀態的偏差就會全部壓在其中一邊。

  5. 除了平均,也要看中位數與離散程度 只要有 1 個離群值,整體樣貌就會嚴重扭曲。平均比想像中更脆弱。

  6. 差異很小時,就用 ETW / WPR 追查到原因為止 只憑體感爭論,雙方的主張都沒有依據,只會平行線下去。

圖中實線表示始終成立的關係,虛線表示附帶條件的關係(成立條件寫在詳細頁面中各關係的說明中)。關係的完整清單(共 25 條,附依據與可信度)以及主要概念的定義,彙整在知識地圖詳細頁面(日文)。資料:JSON-LD / Turtle

先決定你要比較什麼

同樣說是「速度比較」,其實分成 2 種。

1. 想看程式碼差異的比較

想知道演算法變更、資料結構變更、編譯器最佳化、執行階段更新等等,是否讓 實作本身變快 的比較。

這種情況要盡量削掉環境雜訊。 基準測試專用的工作階段、固定 Power mode(電源模式)、停用通知、抑制搜尋索引與同步,必要時做到全新啟動(clean boot)。

2. 想看真實使用者體感的比較

想知道散發之後,使用者在平常的 Windows 上實際感受到的速度。

這種情況 不能把現實中存在的雜訊全部消掉。 在包含 OneDrive 同步、Defender、通知、一般電源設定的「像日常一樣的環境」下比較,結果才會貼近現實。

把這 2 種混在一起,結論就會扭曲。 「實驗室裡快 12%,在現實中卻只是誤差」「在現實中比較快,但 CPU 時間沒有變化」這類情況很常發生。

不要把兩種比較混在一起說明想看程式碼差異的比較要盡量削掉環境雜訊,想看真實使用者體感的比較則要在保留現實雜訊的日常環境下量測,兩者混在一起會讓結論扭曲的圖。程式碼差異真實使用者體感混在一起要比較什麼削掉雜訊的實驗室環境保留雜訊的日常環境結論會扭曲

圖 2: 目的不同,該對齊的環境剛好相反,所以要先決定這是哪一種比較。

Windows 上讓結果浮動的主因

先粗略把會讓結果亂跳的因素列成一張表。

層 浮動因素 典型例子
硬體 CPU / GPU、記憶體、SSD、散熱 筆記型電腦的厚薄、有沒有散熱底座
韌體 BIOS / UEFI、OEM 控制 省電原則、風扇控制
OS Windows build、驅動程式、更新狀態 同一台電腦更新後行為就變了
電源 AC / DC、Power mode(電源模式)、Power plan(電源計劃) 改用電池供電就是另一個世界
溫度 室溫、風扇、前一刻的負載 只有第 1 次進 turbo,後半就失速
背景 Update、Defender、同步、通知 執行途中跑起掃描或同步
排程 優先權、親和性、NUMA 電腦不同,CPU 的配置就不同
資料 / 快取 OS 快取、應用程式快取 只有第一次慢,第 2 次以後才快
建置條件 Debug / Release、PGO、有沒有日誌 根本就在比較不同的東西

簡單說,即使是「同一台 Windows 電腦」,只要條件沒有對齊,就是不同的實驗。

條件沒對齊就是不同的實驗說明就算在同一台 Windows 電腦上量測,從硬體、電源、溫度、背景到建置條件這些橫跨多層的條件若沒有對齊,實質上就是不同的實驗,把條件固定並記錄下來才算是比較的圖。條件沒有對齊固定並記錄多層的條件在同一台 Windows 電腦上量測實質上是不同的實驗這樣才算是比較

圖 3: 就算是同一台電腦,橫跨各層的條件沒有對齊,比較就不成立。

Power mode(電源模式)與 Power plan(電源計劃)要分開看

這一段相當重要。

Windows 上同時有設定應用程式裡的 Power mode(電源模式),以及傳統的 Power plan(電源計劃)(powercfg 看得到的電源計劃)。 兩者外觀相似,很容易被混為一談,但處理得草率,比較條件就會變得含糊,結果也失去重現性。

在 Windows 的設定應用程式中,可以從 Settings > System > Power & battery 選擇 Power mode。 Microsoft 的文件指出,可以針對 Plugged in / On Battery 分別切換 Best power efficiency、Balanced、Best performance。而且 Power mode 一旦改變,背後的電源相關設定與 PPM(Processor Power Management)的行為也會受到影響。也就是說,光是這裡不同,core parking 與效能調節的策略就可能改變。

另一方面,Power plan 是 Balanced、High performance 這類傳統的電源計劃。 可以用 powercfg /list 或 powercfg /getactivescheme 查看。

麻煩的地方在於,Windows 上同時存在 Power mode(電源模式)的 overlay 與 Power plan(電源計劃)。 把兩者的關係畫成圖,就是下面這樣。

下層:Power plan - 電源計劃BalancedHigh performancecustom plan上層:Power mode - overlayBest power efficiencyBalancedBest performance設定應用程式Power and battery 的 Power mode用 powercfg /setactive 切換實際生效的電源設定PPM 與圖形的子群組接 AC 還是用電池頻率上限 / core parking / 效能調節

圖 4: Power mode(overlay)與 Power plan 這兩層再加上 AC/DC,共同決定實際生效的電源設定。

只看上層或只看下層,都無法決定實際的行為。因此在基準測試結果中,至少要記錄下面這些。

  • 接 AC 還是用電池
  • Power mode 是哪一個
  • Active power plan 是哪一個

沒有寫下這 3 項的基準測試結果,日後回頭看時無法還原當時的條件。

至少要記錄的 3 個項目說明接 AC 還是用電池、Power mode 是哪一個、Active power plan 是哪一個這 3 項若沒有和結果一起記錄下來,日後回頭看時就無法還原條件的圖。接 AC 還是用電池和結果一起記錄下來Power modeActive power plan日後可以還原條件

圖 5: 電源相關的這 3 項,沒寫下來的話整份結果都會無法重現,是最低限度的紀錄。

首先要固定的電源條件

  1. 筆記型電腦一定要接 AC 再比較 使用電池時,很容易被加上非預期的限制。

  2. 固定 Power mode 如果是基準測試用途,可以先試 Best performance。

  3. 記錄 Active power plan 用 powercfg 把當下的值留下來。

powercfg /list
powercfg /getactivescheme

powercfg /list 的輸出,在 Microsoft 的文件中是以下面的形式呈現。作用中的配置會在行尾加上 *。在日文環境下,標題與配置名稱會以日文顯示。

Existing Power Schemes (* Active)
-----------------------------------
Power Scheme GUID: {guidPlan1}  (Balanced) *
Power Scheme GUID: {guidPlan2}  (Power saver)

把這裡出現的 GUID 原封不動抄到結果檔案的 power_plan 欄位。重點是留下 GUID 而不是名稱。因為即使同樣叫「平衡」,也可能是複製或自訂出來的另一個配置。

  1. 必要時切換到 High performance
# Balanced
powercfg /setactive 381b4222-f694-41f0-9685-ff5bb260df2e

# High performance
powercfg /setactive 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c

Power mode 能不能用命令列切換

這裡是常見的卡關處。在 powercfg 公開的命令列選項清單中,沒有可以直接改選 Power mode(overlay)本身的選項。正規的做法是從設定應用程式的 Settings > System > Power & battery 切換。

另一方面,powercfg 支援對 overlay scheme 讀寫設定值。文件中有下列敘述。

  • 把 overlay 的別名與子群組傳給 powercfg /q,可以讀取 overlay 這一側的設定
  • powercfg /setacvalueindex 與 /setdcvalueindex 也可以用在 overlay scheme 上
  • 沒有指定 scheme 時,對象是 目前作用中的 overlay(沒有 overlay 時則是目前的電源計劃)
  • 別名的清單可以用 powercfg /aliases 查看

換句話說,命令列能做的是「讀取並調整目前生效的 overlay 內容」,而不是改變「要選哪一個 overlay」。就基準測試的重現步驟而言,在設定應用程式中用人手固定 Power mode,再把該值寫進結果才是可行的做法。操作手冊上要明確寫出「已將 Power mode 設定為 Best performance」,而且每次執行前都在畫面上確認。

powercfg 做得到與做不到的事說明 powercfg 支援讀寫目前生效的 overlay 設定值,但沒有選項可以改變要選哪一個 overlay,因此 Power mode 只能在設定應用程式中用人手固定並記錄下來的圖。做得到做不到powercfg讀取並調整 overlay 的內容改變要選哪一個 overlay在設定應用程式中用人手固定並記錄

圖 6: overlay 的選擇無法用命令列改變,只能用人手固定並記錄下來。

「找不到 High performance」是很常見的事

這裡也是常見陷阱。 Microsoft 的文件指出,在支援 Modern Standby 的裝置上,只允許 Balanced 或從 Balanced 衍生出來的配置。 所以不是「找不到 High performance,是不是壞掉了?」,而是 這台機種的設計本來就是如此 的可能性很高。

另外,Microsoft 也說明:「如果 Power mode 無法變更,可能是選到了 custom power plan,先試著選 Balanced」。Power mode 的 UI 沒有反應時,先從這裡懷疑會比較快。

找不到 High performance 時該怎麼看說明在支援 Modern Standby 的裝置上只允許 Balanced 或其衍生配置,因此看不到 High performance 是設計使然,而 Power mode 的 UI 無法變更時要先懷疑選到了 custom plan 的圖。找不到 High performance支援 Modern Standby 就是設計如此Power mode 的 UI 沒有反應懷疑是 custom plan先試著選 Balanced

圖 7: 配置沒出現、UI 沒反應不一定是故障,先看機種的設計與選到的配置。

排除背景雜訊

就算這邊想安靜地量測,Windows 仍然會在背後跑更新、建立索引與掃描。第一步是把這些活動的量降下來。

先重新開機,等它穩定下來

變更設定之後先重新開機,登入後不要馬上執行,等幾分鐘。 剛啟動時,更新、索引、同步、Defender 與各種常駐程式都還在活動。

重新開機後等它穩定下來說明變更設定後先重新開機,由於剛啟動時更新、索引、同步與 Defender 都還在動作,因此登入後不要馬上執行,等幾分鐘再開始量測的步驟的圖。變更設定重新開機一次登入後等幾分鐘然後才開始量測剛啟動時常駐程式還在活動

圖 8: 要等重新開機後背景活動穩定下來,才開始量測。

需要嚴謹比較時就用全新啟動

Microsoft 說明了以全新啟動把啟動時的設定縮到最小的步驟: 用 msconfig 停用 Microsoft 以外的服務,再用工作管理員停用 Startup apps。

這個做法在 減少雜訊 上很有效。 但它離日常使用環境很遠,比較適合用在「為了看程式碼差異的實驗室比較」。

讓通知安靜下來

Windows 的通知橫幅看起來不起眼,其實相當礙事。 它不只是視覺上的干擾,還可能改變執行時機、焦點,以及背景應用程式的活動。

手動啟用 Do not disturb,或至少在基準測試期間把通知關掉。

抑制搜尋索引與同步

如果受測對象會讀取大量檔案、寫出大量產出物,或反覆重建原始碼樹,搜尋索引與雲端同步就會不動聲色地拖累結果。

  • 把基準測試用的目錄排除在搜尋範圍之外
  • 停掉 OneDrive / Dropbox / Google Drive 等的同步
  • 關掉瀏覽器、Teams、Discord、Slack

這些做法都不起眼,但該有效的時候相當有效。

會拖累大量存取檔案的基準測試的雜訊說明在會大量讀寫檔案的基準測試中,搜尋索引、雲端同步與常駐應用程式都會拖累量測,因此要用排除設定或停用來減少雜訊的圖。搜尋索引拖累大量存取檔案的基準測試雲端同步常駐應用程式用排除或停用來減少雜訊

圖 9: 讀寫檔案越多的基準測試,停用索引與同步的效果越明顯。

不對齊溫度的比較,多半是在比溫度

CPU 與 GPU 在冷的時候和熱起來之後,運作時脈並不相同。也就是說,即使是同一份程式碼,每次執行的條件都在變。 筆記型電腦、薄型迷你電腦、小型桌上型電腦尤其明顯。

溫度改變條件的機制說明 CPU 與 GPU 在冷的時候和熱起來之後運作時脈不同,因此同一份程式碼每次執行的條件都在變,不對齊溫度的比較多半是在比溫度的機制的圖。在冷的狀態下執行熱起來後時脈改變每次執行條件都在變不對齊的比較是在比溫度

圖 10: 時脈會隨溫度變動,不對齊溫度條件就會變成在比較散熱而不是程式碼。

要遵守的規則

  • 盡量對齊室溫
  • 固定筆記型電腦的擺放方式
  • 固定 AC 變壓器、擴充座與外接顯示器的接法
  • 基準測試之前不要做繁重的工作
  • 把第一次執行與穩態分開量測

執行順序要交替

要避免先跑 A 十次再跑 B 十次。 因為溫度、快取與背景活動的偏差會壓在其中一邊。

建議採用下面其中一種。

  • A B A B A B ...
  • A B B A A B B A ...
  • 事先產生隨機順序,再依該順序執行
執行順序會改變偏差落在哪一邊說明先把 A 全部跑完再跑 B 會讓溫度、快取與背景活動的偏差只壓在其中一邊,改成交替或隨機順序執行則能把偏差分散到兩邊的圖。A 全部跑完 → 再跑 B 全部偏差只壓在其中一邊A B A B 交替或隨機順序偏差分散到兩邊可以把順序的影響從差異中排除

圖 11: 把順序集中起來就會連偏差一起比較,所以要交替或隨機執行。

量測的對象不同,「快」的意思也不同

把「快」壓進 1 個數字裡,多半會出事。 在 Windows 上該看的代表性指標有下面 3 個。

1. Wall-clock time(實際經過時間)

使用者實際在等的時間。 最貼近端對端的體感,所以第一個要看的就是這個值。

在 Windows 上,QueryPerformanceCounter (QPC) 可以用來取得高解析度的時間。 受管理的程式碼(managed code)則基本上使用 Stopwatch 這一系列。 用 DateTime.Now 去看毫秒,實在有點不保險。

2. CPU time(使用者時間 + 核心時間)

可以用 GetProcessTimes 取得,是處理程序實際使用 CPU 的時間。

這個指標很適合用來 看計算效率。 舉例來說,如果 wall-clock 變快了但 CPU time 沒有變化,那可能是快取、I/O、等待時間或排程在起作用。

3. Cycle count(CPU 週期數)

用 QueryProcessCycleTime 可以取得整個處理程序的 CPU 週期數。

這同樣是看 CPU work 的指標,但呈現的面向與 wall-clock 不同。 特別是想看「等待時間相同,但計算的部分是否變輕了」的時候很好用。

3 個指標所看的面向差異說明 wall-clock time 是使用者在等的時間、CPU time 是處理程序實際使用 CPU 的時間、cycle count 是 CPU 週期數,三者呈現不同的面向,組合起來才能讀出快的內涵的圖。看清楚「快」的內涵wall-clock:等待的時間CPU time:用掉的 CPU 時間cycle:計算部分的份量用組合來推測理由

圖 12: 不要壓進 1 個數字,用 3 個指標的組合來讀出「快」的意義。

priority、affinity、NUMA 是最後的手段

這一類設定有時候確實有效。 但正因為有效,一開始就動它,很容易製造出另一種現象。

先用一般狀態量測

如果在預設狀態下就出現差異,那個差異本身就有價值。 一開始就加上 /high 或 /affinity,等於帶入 「實際的 Windows 上不會發生的條件」。

priority 與 affinity 是最後的手段說明先在預設狀態下量測,有差異的話那個差異本身就有價值,一開始就固定優先權或親和性等於帶入實際 Windows 上不會發生的條件,因此要用時得先確定目的並放到最後的圖。有需要時再確定目的先用預設狀態量測有差異的話那個差異就有價值一開始就用 /high 或 /affinity帶入現實不會發生的條件當成最後的手段來固定

圖 13: 優先權與親和性,要在完成預設狀態的量測之後,帶著目的再使用。

要用就要把目的講清楚

  • /high:不想受到其他處理程序的干擾
  • /affinity:想固定 CPU 的配置再比較
  • NUMA 控制:想在大型電腦上連記憶體區域性一起對齊

Windows 的 start 命令可以帶著 priority class 或 affinity mask 來啟動程式。

start "" /high /wait myapp.exe --bench case1.json
start "" /affinity F /high /wait myapp.exe --bench case1.json

但是不要用 /realtime

/realtime 雖然可以用,但 最好不要用。 它往往不是在去除雜訊,而是往製造另一種事故的方向作用。

建議的量測步驟

根據前面的內容,整理出實務上好操作的步驟。

偏實驗室的比較步驟

  1. 固定比較對象
    • commit hash / build number
    • compiler / runtime version
    • Debug / Release
    • 日誌、assert、追蹤的有無
  2. 固定電腦條件
    • Windows build
    • BIOS / UEFI version
    • driver version
    • 接 AC
    • 室溫、擺放方式
  3. 固定電源條件
    • 決定 Power mode
    • 記錄 Active power plan
  4. 重新開機
  5. 基準測試前等幾分鐘
  6. 必要時做全新啟動
  7. 加入 warm-up
  8. A / B 交替執行
  9. 確保執行次數
  10. 留下中位數、最小值、最大值與 p95
  11. 保存 raw data
  12. 差異很小時就取 ETW / WPR

要跑幾次

第 9 點「確保執行次數」的大致參考值也先定下來。以下不是統計上的嚴格解,而是實務上的折衷點。

想看的東西 每個版本的執行次數參考值
只看中位數,想確認較大的差異(1 成以上) 10 次
想主張數 % 的差異,也想看離散程度 30 次
想讀到 p95 30 次以上。只跑 20 次的話,p95 會直接落在最上面的 1〜2 個值本身,會直接受到離群值的影響

所需時間可以用 單次執行時間 × 次數 × 版本數 + warm-up 來估算。單次 30 秒的處理,A / B 各跑 30 次,加上 warm-up 大約是 35 分鐘左右。如果這不切實際,比起減少次數,把量測對象切小(只把繁重的工序切出來)方向會比較對。

如果不知道該在哪裡收手,一邊增加次數一邊看中位數的變化,等到再增加也不動時就停下來,是比較好懂的做法。

執行次數的收手時機說明一邊增加次數一邊觀察中位數的變化,等到再增加中位數也不再變動時就停下來,這種決定執行次數的實務做法的圖。還在動增加也不動了增加次數繼續跑觀察中位數的變化就在這裡停下來

圖 14: 就算無法事先把次數定死,也可以把中位數穩定下來的點當成收手時機。

先記錄下來、日後會派上用場的項目

基準測試的 CSV 或 JSON 中,至少留下下面這些會很有幫助。

timestamp,version,scenario,elapsed_ms,user_ms,kernel_ms,cycles,power_mode,power_plan,ac_or_dc,room_temp_c,notes

如果可以,再加上下面這些會更方便。

cpu_package_temp_start_c,cpu_package_temp_end_c,affinity_mask,priority_class,windows_build,driver_version

基準測試有時候 事後能不能解釋 比 量測本身 更重要。

除了平均,也要看中位數與分佈

平均很方便,但在 Windows 的基準測試中很容易壞掉。 只要有 1 次 Defender 插進來、跳出通知,或別的處理程序去敲 SSD,平均就被帶走了。

平均會被離群值帶走說明只要有一次 Defender 掃描、通知或別的處理程序的 I/O 插進來,平均就會被帶走,因此要以中位數為軸,再搭配 p95、p99 與 min/max 用分佈來讀的圖。只有 1 次混進雜訊平均被帶走以中位數為軸也看 p95 / p99 與 min / max變成對離群值有抵抗力的讀法

圖 15: 平均會被 1 次雜訊弄壞,所以要用中位數與分佈的組合來讀。

建議採用這個組合。

  • 中位數:先看這個
  • p95 / p99:看 tail 有沒有惡化
  • min / max:看離群的程度
  • 箱型圖或散佈圖:差異很小時派得上用場

出現差異時的讀法

解讀結果時,把指標組合起來看會比較清楚。

只有 wall-clock 變快

可能是 I/O、等待時間、快取或排程獲得改善。

CPU time 與 cycle 都下降

實作本身變輕的可能性很高。

只有第 1 次慢或快

這是 cold / warm 的差異。懷疑啟動、初始化、快取產生與 JIT。

跑越多次越慢

懷疑溫度、throttling、記憶體壓力與背景活動。

從差異的樣態讀出原因說明只有 wall-clock 變快就懷疑等待與 I/O,CPU time 與 cycle 也下降就是實作變輕,只有第一次不同就是 cold 與 warm 的差異,跑越多次越慢就懷疑溫度與背景活動的讀法的圖。只有實際時間CPU 時間也減少只有第一次後半變慢看差異出現的樣態等待與 I/O 相關實作變輕cold / warm溫度與背景活動

圖 16: 比起差異本身,差異出現的樣態更能指出原因的方向。

用 ETW / WPR 挖到「為什麼比較快」

差異很小,或看不出理由的時候,往 Windows 的 ETW(Event Tracing for Windows)系工具走是最正統的做法。

Microsoft 的 Windows Performance Recorder (WPR) 是以 ETW 為基礎的記錄工具,包含在 Windows ADK 中。 CPU、I/O、內容切換(context switch)、分頁錯誤等等可以一起取得。

最基本的用法像下面這樣。

wpr -start CPU -filemode

REM 在這裡執行基準測試

wpr -stop trace.etl

用 WPA 開啟之後,最先要看的圖表大致上是固定的。

想看的東西 要開啟的圖表 讀法
哪個函式在用 CPU CPU Usage (Sampled) 以 Weight 排序,比較 A 與 B 的堆疊。因為是取樣,DPC / ISR 這種很短的處理不容易被拍到
為什麼在等 CPU Usage (Precise) 查看 Ready 時間、等待時間與內容切換的原因。lock 等待與 I/O 等待的差異會出現在這裡
是不是驅動程式造成的卡住 DPC/ISR 查看各模組的時間。這裡的數值很大的話,差異根本不在應用程式這一側
磁碟是不是在起作用 Disk Usage 查看 I/O 的次數與大小,以及服務時間

比較時的基本做法是 在相同情境下各取一份 A 與 B 的追蹤,把同樣的圖表並排來看。只看一份是無法判斷「這樣算慢嗎」的。

走到這個階段,就不再只是 「B 快 3%」, 而能像 「B 的 lock 等待減少,ready time 下降了」 「A 的 file open 變多,cold start 比較慢」 這樣,帶著理由把事情說清楚。

從只有數字的差異走到帶理由的差異說明差異很小或看不出理由時,用 WPR 在相同情境下各取一份 A 與 B 的追蹤,再用 WPA 把同樣的圖表並排比較,就能從快幾 % 變成帶著理由說明的流程的圖。差異很小、看不出理由用 WPR 取得 A 與 B 的追蹤用 WPA 把同樣的圖表並排來看能帶著理由把事情說清楚只看一份無法判斷是不是慢

圖 17: 挖到 ETW 這一層,「快幾 %」就會變成「為什麼快」。

一頁式檢查清單

最後整理成可以直接貼進操作手冊的形式。

固定

  • 已固定比較對象(commit hash / build number / Debug 或 Release / PGO 等建置條件 / 有沒有日誌與 assert)
  • 已把筆記型電腦接上 AC
  • 已在設定應用程式中固定 Power mode
  • 已用 powercfg /getactivescheme 查看 Active power plan
  • 已停用通知,並停掉搜尋索引與雲端同步
  • 必要時已改成全新啟動
  • 已重新開機,並等幾分鐘後才開始

執行

  • 已加入 warm-up
  • 已把 cold(第一次)與 warm(穩態)分開量測
  • 已用交替或隨機順序執行 A / B
  • 已決定次數後執行(參考值見上面的表)

記錄

  • 已留下每次執行 1 列的 raw data(elapsed_ms / user_ms / kernel_ms / cycles)
  • 已留下接 AC 還是 DC、Power mode(電源模式)、Power plan(電源計劃)的 GUID、Windows build 與 driver version
  • 已留下室溫與擺放狀態
  • 也寫下了沒有固定的條件

解讀

  • 已查看中位數,沒有只用平均判斷
  • 已用 p95 / p99 查看 tail
  • 已用 min / max 確認離群值
  • 已用 wall-clock / CPU time / cycle 的組合推測理由
  • 差異很小時已挖到 ETW / WPR

總結

在 Windows 上比較不同版本的程式時,真正管用的不是花俏的旁門左道。 重要的是下面這些 不起眼卻對重現性很有用的做法。

  • 固定並記錄 AC / Power mode(電源模式) / Power plan(電源計劃)
  • 把 cold 與 warm 分開
  • A / B 交替執行
  • 查看中位數與分佈
  • 必要時做全新啟動
  • 差異很小時就用 ETW / WPR 挖到理由

而最重要的是,把固定了什麼、沒有固定什麼和結果寫在一起。 基準測試既是速度的比較,同時也是實驗條件的紀錄。

沒有寫下條件的加速報告,別人無法確認能不能做出相同的結果。因為只留下數字,卻沒有留下重現的方法。 反過來說,只要條件寫得完整,就算差異很小,那份結果也確實有價值。

條件的紀錄決定結果的價值說明沒有寫下條件的加速報告只留下數字、沒有留下重現的方法,條件寫得完整就算差異很小也有價值,也就是基準測試同時是實驗條件的紀錄的圖。沒有寫下條件的報告只留下數字別人無法確認寫下條件的報告留下重現的方法就算差異很小也有價值

圖 18: 基準測試的價值不在數字,而在於固定了什麼、沒固定什麼的紀錄。

參考資料

共用相同標籤的最新文章。能以相近的主題延伸理解。

與本文相近的主題頁面。以本文為起點,可進一步連到相關服務與其他文章。

本文連結到以下服務頁面,歡迎從最接近的入口查看。

常見問題

整理諮詢這個主題時常見的問題。

在 Windows 上,基準測試結果浮動的主要原因是什麼?
原因橫跨多個層次:Power mode(電源模式)、Power plan(電源計劃)、溫度、背景更新、搜尋索引、病毒掃描、優先權與親和性、執行順序、快取狀態等等。即使是同一台 Windows 電腦,只要這些條件沒有對齊,實質上就是不同的實驗。筆記型電腦特別明顯,接 AC 與使用電池的行為差很多,因此一定要在接 AC 的狀態下比較,並把條件記錄下來。
Power mode(電源模式)與 Power plan(電源計劃)有什麼不同?
Power mode 是在設定應用程式的 Power & battery 中選擇 Best power efficiency、Balanced、Best performance 的切換,會影響背後的電源相關設定與 PPM(Processor Power Management)的行為。Power plan 則是用 powercfg 可以查看的 Balanced、High performance 等傳統電源計劃。Windows 上兩者同時存在,因此基準測試結果至少要記錄接 AC 還是用電池、Power mode、Active power plan 這三項。
找不到 High performance 電源計劃,是故障嗎?
多半不是故障。Microsoft 的文件指出,在支援 Modern Standby 的裝置上,只允許 Balanced 或從 Balanced 衍生出來的配置。也就是說,因為機種的設計而看不到 High performance 是很常見的情況。另外,如果 Power mode 的 UI 無法變更,可能是選到了 custom power plan,先試著選 Balanced 會比較快找到答案。
比較 A 版與 B 版的速度時,應該用什麼順序執行?
應該避免先把 A 全部跑完再跑 B,因為溫度、快取與背景活動的偏差會只壓在其中一邊。改成 A B A B 交替執行,或依事先產生的隨機順序執行。此外,把冷機的第一次與熱機後的穩態分開量測,並且不只看平均,還要看中位數、p95、最小值與最大值,就能避免結果被離群值帶走。

作者檔案

本文作者的個人檔案頁面。

Go Komura

小村軟體有限公司 代表

以 Windows 軟體開發、技術諮詢與故障調查為中心,在難以重現的故障調查與既有資產仍在運作的專案上具有優勢。

回到部落格一覽