Flutter 效能分析
有人說:「一個快的應用程式很棒,但一個流暢的應用程式更好。」如果您的應用程式無法順暢渲染,您該如何修復?您該從何開始?本指南將說明從何開始、應採取的步驟以及可提供協助的工具。
診斷效能問題
#若要診斷具有效能問題的應用程式,您需要啟用效能覆蓋圖以查看 UI 和光柵執行緒。在開始之前,請確保您正在 Profile 模式下執行,並且您未使用模擬器。為了獲得最佳結果,您可能會選擇您的使用者可能會使用的最慢裝置。
連接實體裝置
#Flutter 應用程式的幾乎所有效能除錯都應該在實體 Android 或 iOS 裝置上進行,並且您的 Flutter 應用程式在 Profile 模式下執行。使用除錯模式或在模擬器上執行應用程式,通常無法表示發行模式建置的最終行為。您應該考慮在您的使用者可能合理使用的最慢裝置上檢查效能。
以 Profile 模式執行
#Flutter 的 Profile 模式會以幾乎與發行模式相同的方式編譯和啟動您的應用程式,但具有足夠的額外功能,可讓您除錯效能問題。例如,Profile 模式會為效能分析工具提供追蹤資訊。
依照下列方式在 Profile 模式下啟動應用程式
在 VS Code 中,開啟您的
launch.json
檔案,並將flutterMode
屬性設定為profile
(效能分析完成後,將其改回release
或debug
)json"configurations": [ { "name": "Flutter", "request": "launch", "type": "dart", "flutterMode": "profile" } ]
在 Android Studio 和 IntelliJ 中,請使用 執行 > 以 Profile 模式執行 Flutter main.dart 功能表項目。
從命令列中,使用
--profile
旗標flutter run --profile
如需有關不同模式的詳細資訊,請參閱 Flutter 的建置模式。
您將從開啟 DevTools 並檢視效能覆蓋圖開始,如下一節所述。
啟動 DevTools
#DevTools 提供諸如效能分析、檢查堆積、顯示程式碼覆蓋率、啟用效能覆蓋圖和逐步除錯器等功能。DevTools 的 時間軸檢視器可讓您逐幀調查應用程式的 UI 效能。
在您的應用程式以 Profile 模式執行後,啟動 DevTools。
效能覆蓋圖
#效能覆蓋圖會在兩個圖表中顯示統計資料,這些圖表顯示時間在您的應用程式中花費的位置。如果 UI 卡頓 (跳過幀),這些圖表可協助您找出原因。這些圖表會顯示在您執行中的應用程式之上,但它們不是像一般 Widget 那樣繪製的——Flutter 引擎本身會繪製覆蓋圖,並且只會對效能產生最低限度的影響。每個圖表都代表該執行緒的最後 300 個幀。
本節說明如何啟用效能覆蓋圖並使用它來診斷應用程式中發生卡頓的原因。以下螢幕擷取畫面顯示在 Flutter Gallery 範例上執行的效能覆蓋圖
顯示光柵執行緒 (頂部) 和 UI 執行緒 (底部) 的效能覆蓋圖。
垂直綠色長條代表目前的幀。
解讀圖表
#頂部圖表 (標記為「GPU」) 顯示光柵執行緒所花費的時間,底部圖表顯示 UI 執行緒所花費的時間。圖表上的白色線條顯示垂直軸上以 16 毫秒為增量的間隔;如果圖表超過其中一條線,則表示您的執行速度低於 60Hz。水平軸代表幀。圖表只會在您的應用程式繪製時更新,因此如果它處於閒置狀態,則圖表會停止移動。
覆蓋圖應始終在 Profile 模式下檢視,因為 除錯模式的效能會故意為了交換用於輔助開發的昂貴斷言而被犧牲,因此結果具有誤導性。
每個幀都應在 1/60 秒 (約 16 毫秒) 內建立和顯示。超過此限制 (在任一圖表中) 的幀無法顯示,導致卡頓,並且垂直紅色長條會出現在其中一個或兩個圖表中。如果 UI 圖表中出現紅色長條,則表示 Dart 程式碼過於耗費資源。如果 GPU 圖表中出現紅色垂直長條,則表示場景過於複雜而無法快速渲染。
垂直紅色長條表示目前幀的渲染和繪製成本都很高。
當兩個圖表都顯示紅色時,請從診斷 UI 執行緒開始。
Flutter 的執行緒
#Flutter 使用多個執行緒來完成其工作,儘管覆蓋圖中僅顯示其中兩個執行緒。您的所有 Dart 程式碼都在 UI 執行緒上執行。儘管您無法直接存取任何其他執行緒,但您在 UI 執行緒上的動作會對其他執行緒的效能產生影響。
- 平台執行緒
- 平台的 Main 執行緒。外掛程式程式碼在此處執行。如需詳細資訊,請參閱 iOS 的 UIKit 文件,或 Android 的 MainThread 文件。此執行緒不會顯示在效能覆蓋圖中。
- UI 執行緒
- UI 執行緒會在 Dart VM 中執行 Dart 程式碼。此執行緒包含您撰寫的程式碼,以及 Flutter 框架代表您的應用程式執行的程式碼。當您的應用程式建立並顯示場景時,UI 執行緒會建立圖層樹,這是一個包含與裝置無關的繪圖命令的輕量級物件,並將圖層樹傳送到光柵執行緒以在裝置上進行渲染。不要封鎖此執行緒!顯示在效能覆蓋圖的底部列中。
- 光柵執行緒
- 光柵執行緒會取得圖層樹,並透過與 GPU (圖形處理單元) 通訊來顯示它。您無法直接存取光柵執行緒或其資料,但是,如果此執行緒速度緩慢,則表示您在 Dart 程式碼中進行了某些操作。Skia 和 Impeller 這兩個圖形庫在此執行緒上執行。顯示在效能覆蓋圖的頂部列中。請注意,雖然光柵執行緒會為 GPU 進行光柵化,但該執行緒本身是在 CPU 上執行的。
- I/O 執行緒
- 執行耗費資源的任務 (主要為 I/O),否則會封鎖 UI 或光柵執行緒。此執行緒不會顯示在效能覆蓋圖中。
如需更多資訊和影片的連結,請參閱 框架架構,位於 Flutter 維基中,以及社群文章 圖層蛋糕。
顯示效能覆蓋圖
#您可以透過以下方式切換效能覆蓋層的顯示:
- 使用 Flutter Inspector
- 從命令列
- 以程式碼方式
使用 Flutter Inspector
#啟用 PerformanceOverlay 小工具最簡單的方式是透過 Flutter Inspector,它位於 DevTools 的 Inspector 視窗中。只需點擊「效能覆蓋層」按鈕,即可切換正在執行的應用程式上的覆蓋層。
從命令列
#從命令列使用 P 鍵切換效能覆蓋層。
以程式碼方式
#若要以程式碼方式啟用覆蓋層,請參閱效能覆蓋層,此部分位於以程式碼方式偵錯 Flutter 應用程式頁面中。
識別 UI 圖表中的問題
#如果效能覆蓋層在 UI 圖表中顯示紅色,請先分析 Dart VM,即使 GPU 圖表也顯示紅色。
識別 GPU 圖表中的問題
#有時,場景會產生一個容易建構的圖層樹狀結構,但在 raster 執行緒上渲染的成本很高。當發生這種情況時,UI 圖表沒有紅色,但 GPU 圖表顯示紅色。在這種情況下,您需要找出您的程式碼中哪些部分導致渲染程式碼變慢。某些特定的工作負載對 GPU 來說比較困難。它們可能涉及不必要的 saveLayer
呼叫、多個物件交錯的不透明度,以及特定情況下的剪裁或陰影。
如果您懷疑速度變慢的原因是在動畫期間,請點擊 Flutter Inspector 中的「慢速動畫」按鈕,將動畫速度減慢 5 倍。如果您想要更精確地控制速度,您也可以以程式碼方式進行。
是第一幀的速度慢,還是整個動畫的速度慢?如果是整個動畫的速度慢,是否是剪裁導致速度變慢?也許有其他繪製場景的方法,不需要使用剪裁。例如,將不透明的角落覆蓋在正方形上,而不是剪裁成圓角矩形。如果是一個靜態場景,正在進行淡入、旋轉或其他操作,則 RepaintBoundary
可能會有幫助。
檢查螢幕外圖層
#saveLayer
方法是 Flutter 框架中最耗費資源的方法之一。當對場景應用後處理時,它很有用,但它會減慢您的應用程式速度,如果不需要,應該避免使用它。即使您沒有明確呼叫 saveLayer
,也可能會代表您進行隱含呼叫,例如在指定 Clip.antiAliasWithSaveLayer
(通常作為 clipBehavior
) 時。
例如,您可能有一組具有不透明度的物件,它們是使用 saveLayer
渲染的。在這種情況下,將不透明度套用到每個個別小工具,可能比套用到小工具樹中較高的父小工具更有效能。對於其他可能耗費資源的操作,例如剪裁或陰影,也是如此。
當您遇到 saveLayer
的呼叫時,請自問以下問題:
- 應用程式是否需要此效果?
- 是否可以消除任何這些呼叫?
- 我可以將相同的效果套用到個別元素而不是群組嗎?
檢查未快取的影像
#使用 RepaintBoundary
快取影像很好,在有意義的情況下。
從資源角度來看,最耗費資源的操作之一是使用影像檔案渲染紋理。首先,從永久儲存空間提取壓縮的影像。影像解壓縮到主機記憶體 (GPU 記憶體),並傳輸到裝置記憶體 (RAM)。
換句話說,影像 I/O 可能很耗費資源。快取提供複雜階層的快照,以便在後續幀中更容易渲染。由於點陣快取項目建構成本很高,且佔用大量 GPU 記憶體,因此只在絕對必要時快取影像。
檢視 Widget 重建分析器
#Flutter 框架的設計目的是讓開發難以建立不是 60fps 且不流暢的應用程式。通常,如果您有卡頓,那是因為有一個簡單的錯誤導致每幀重建的 UI 比需要的還要多。小工具重建分析器可協助您偵錯和修正因這些錯誤引起的效能問題。
您可以在 Android Studio 和 IntelliJ 的 Flutter 外掛程式中檢視目前螢幕和幀的小工具重建計數。有關如何執行此操作的詳細資訊,請參閱顯示效能資料
基準測試
#您可以透過編寫基準測試來測量和追蹤應用程式的效能。Flutter Driver 程式庫提供對基準測試的支援。使用此整合測試框架,您可以產生指標來追蹤以下項目:
- 卡頓
- 下載大小
- 電池效率
- 啟動時間
追蹤這些基準測試可讓您在引入對效能產生不利影響的回歸時收到通知。
如需更多資訊,請查看整合測試。
其他資源
#以下資源提供更多有關使用 Flutter 工具和在 Flutter 中偵錯的資訊:
- 偵錯
- Flutter inspector
- Flutter inspector 演講,在 DartConf 2018 上發表
- 為什麼 Flutter 使用 Dart,一篇在 Hackernoon 上的文章
- 為什麼 Flutter 使用 Dart,Flutter 頻道上的影片
- DevTools:Dart 和 Flutter 應用程式的效能工具
- Flutter API 文件,特別是
PerformanceOverlay
類別和 dart:developer 套件
除非另有說明,否則本網站上的文件反映了 Flutter 的最新穩定版本。頁面上次更新時間為 2024-10-24。 檢視原始碼 或 回報問題。