【文章內容使用 Gemini 1.5 Pro 自動產生】
網頁上的效能測試
本文於 2020 年 11 月 25 日更新,以使用 `web_benchmarks` 套件。
概觀
在開發過程中,我們經常希望在瀏覽器中測試應用程式的效能。效能測試很有用,因為它可以揭露可能導致應用程式變慢的潛在錯誤。
本文介紹了一種在 Chrome 中測試應用程式效能的方法。此方法類似於我們測試 新的 Flutter Gallery 效能的方式。
範例應用程式
我們使用一個簡單的應用程式,其中包含一個 appbar、一個浮動動作按鈕和一個無限項目列表。列表還顯示按鈕被按下次數。
應用程式有一個包含一些資訊的第二頁。
您可以在這裡複製應用程式:
測試什麼?
我們希望在以下使用情境下測試應用程式在 Chrome 中的效能:
- 使用者在無限列表中捲軸。
- 使用者在兩個頁面之間切換。
- 使用者點擊浮動動作按鈕。
設定框架
在 pubspec.yaml
中加入以下內容:
此相依性會導入 web_benchmarks,一個實現 Chrome 中效能測試的最小套件。
此套件改編自 macrobenchmarks 和 devicelab,這兩個套件由 Flutter 用於在 Flutter Gallery 上進行網頁效能測試。目前,這兩個套件專門用於 flutter/flutter
中的網頁效能測試,因此導入更通用的套件 web_benchmarks 更容易。
執行 flutter pub get
以導入此套件。
撰寫第一個測試
在 lib
目錄下加入 benchmarks
目錄,並在其中加入一個名為 runner.dart
的新 dart 檔案:
檔案的內容如下:
此測試在做什麼?
- 當此應用程式執行時,會建立一個
ScrollRecorder
物件,它會透過自動執行手勢來驅動應用程式。在本例中,在應用程式啟動後不久,它會開始向下捲軸無限列表。 ScrollRecorder
類別擴展了AppRecorder
類別,AppRecorder
類別擴展了WidgetRecorder
類別,WidgetRecorder
類別還會在驅動應用程式時記錄效能資料。runBenchmarks
是在package:web_benchmarks/client.dart
中定義的函式,它允許使用者選擇要執行的基準測試,並在瀏覽器中顯示結果。automate
方法使用flutter_test
套件,該套件提供了在應用程式中執行手勢或尋找特定 Widget 的方法。
執行第一個測試
在專案的根目錄中,執行 flutter run -d chrome -t lib/benchmarks/runner.dart
。這會指示 Flutter 使用 runner.dart
作為入口點,而不是 main.dart
。
到目前為止,我們只有一個基準測試,因此點擊「捲軸」以啟動它。
測試開始,列表會自動向下捲軸。
測試在幾秒鐘內結束,顯示以下螢幕:
此圖表顯示應用程式繪製每個(記錄的)畫面所需的時間。橫軸表示時間流逝;縱軸表示每個畫面所需的時間。
圖表的前 2/3 部分具有灰色背景;這些畫面被認為是「預熱畫面」,並且從統計資料中省略。預熱畫面通常會讓 JIT 編譯器有時間編譯程式碼並建立各種快取,以便測量畫面能產生反映應用程式「最終」效能的數字,而不是它最初幾秒鐘的效能。預熱階段不應始終被忽略 - 它可以提供應用程式最初幾秒鐘效能的寶貴資訊,這仍然會影響對應用程式品質的感知。
紅色畫面是「異常值」 - 它們是繪製時間比其他畫面顯著長得多的畫面。有些異常值幾乎不可察覺。例如,動畫開始或結束時的卡頓,直到一定程度才會被看見。但是,動畫 中間 的卡頓畫面非常明顯。
異常值很好地表明了應用程式卡頓的程度。透過改進您的應用程式,您可以降低異常值的數值或減少異常值的數量,這表示您的應用程式已變得更流暢。
從 Chrome 的 DevTools 收集資料
此基準測試完全在 Chrome 中執行。將以下檔案新增為 test/run_benchmarks.dart
:
然後,執行 dart test/run_benchmarks.dart
。
大約一分鐘後,您應該看到以下結果:
準確的基準測試數值可能會因機器而異。
此測試在做什麼?
- 執行
test/run_benchmarks.dart
會為網頁構建應用程式。然後,它會啟動一個 Chrome 實例並在其中執行應用程式。 test/run_benchmarks.dart
會連接到 Chrome 的 DevTools 連接埠,並監聽和收集相關的效能資料。
結果的含義是什麼?
- 渲染畫面時,會走訪 層級樹 兩次。
- 「預先處理」是第一次走訪。它不會渲染任何內容,但會計算稍後用於渲染的值。例如:轉換矩陣、轉換的逆矩陣和剪裁。
- 「應用程式畫面」是實際渲染 UI 的第二次走訪。
- 「繪製畫面」是框架渲染畫面所需的時間。它包含「預先處理」和「應用程式畫面」,但它還包含花費在構建和佈局 Widget 上的時間。
- 「總 UI 畫面」包含「繪製畫面」中的所有內容,但它還包含瀏覽器執行的某些隱藏工作,例如層級樹更新、樣式重新計算和瀏覽器端佈局(不要與 Flutter 自己進行的佈局混淆)。
- 收集資料集(持續時間列表)時,演算法會移除異常值。
- 首先,計算資料的平均值和標準差,並且任何比(平均值 + 1 個標準差)高的資料點都被視為異常值。
- 非異常值(乾淨資料)的平均值和標準差用於計算資料集的平均值和雜訊,然後報告這些值。
- 所有異常值的平均值以及「異常值平均值」和「非異常值平均值」的比率也會被報告。
- 對於每個資料集,「異常值比率」和「雜訊」都是應用程式效能中存在多少雜訊的良好指標。如果結果過於雜亂,則可能表示效能不一致(例如,GC 暫停時的卡頓畫面)。透過降低雜訊,您可以使應用程式執行更順暢。
加入更多測試
編輯 lib/benchmarks/runner.dart
以加入兩個更多測試。
首先,修改 main
函式:
最後,加入兩個更多擴展 AppRecorder
的類別:
這些測試在做什麼?
- 我們加入了兩個剩餘的基準測試:一個用於在頁面之間切換,另一個用於點擊浮動動作按鈕。
animationStops
反覆檢查動畫是否正在進行,並在所有動畫停止時停止。這會確保,例如,成功轉換到「關於」頁面。- 在「頁面」和「點擊」基準測試中,
_completed
布林值追蹤自動手勢是否已完成。 - 在「頁面」和「點擊」基準測試中,覆寫
shouldContinue
方法會導致AppRecorder
在 所有手勢完成 後 停止記錄畫面。
如何執行這些測試?
若要在 Chrome 中執行這些測試(並查看動畫),請執行:
flutter run -d chrome -t lib/benchmarks/runner.dart --profile
若要執行這些測試並收集 DevTools 資料,請執行:
dart test/run_benchmarks.dart
接下來要做什麼?
在您有方法收集效能資料後,您可以隨意使用它:
- 您可以為 CI 設定一個作業,只要有人提交 PR 就執行這些基準測試,以避免引入效能負擔大的變更。
- 您也可以設定一個儀表板來追蹤效能基準測試的趨勢。這就是我們對 Flutter Gallery 所做的事情(請參閱 Flutter Dashboard)。