給你們介紹DevTools
的主要緣由主要有幾點 🚀 :git
DevTools
自己是Flutter
官方推薦的一個調試工具。DevTools
是用Flutter
編寫的,極具特點 🖼 。首先,隆重介紹今天的主角:DevTools 👏web
官網介紹:
DevTools is a suite of performance and debugging tools for Dart and Flutter. It’s currently in beta release, but is under active development.
編程翻譯:
DevTools
是Dart
和Flutter
的一套性能和調試工具。它目前處於測試版,但正在積極開發中。後端
要使用DevTools
首先,全部的一切的前提,確定是,裝上它,yes
,這看似簡單的一步其實花了我還蠻久時間的。但願各位安裝順利,我將給各位介紹四種打開DevTools的方法
。瀏覽器
使用以上兩種開發工具的小夥伴看這邊了 🙋♂️,在此類開發工具上打開DevTools
一共分三個步驟markdown
Flutter
插件:首先確認你已經在開發工具內安裝了Flutter
插件(不會有人還沒裝吧,不會吧 👀 )
app
對,就是字面意思,容許你要調試的那個項目工程(推薦使用Profile
模式)。友情提示:Profile
模式只能在真機 📱 上運行。異步
DevTools
的入口其實 DevTools
的入口不是很顯眼,可是還算好找,在底部的工具欄,我們常常用的hot reload
邊上,直接點擊該按鈕 🔘 就能夠啓動該項目的DevTools
。
函數
(PS:我本身用的是Android Studio
,可是我並無經過這種方式成功,一直就是Installing DevTools...
,若是各位知道緣由,歡迎在評論區指點一下,阿里嘎多 🤗 )工具
Flutter
插件:首先確認你已經在開發工具內安裝了Flutter
、Dart
插件(同Android Studio
)
經過在 VS Code
中打開你的項目的根目錄(包含 pubspec.yaml
)並點擊 Run > Debugging
(F5
),來開啓調試會話。
啓動開發程序
VS Code
命令控制板中將會顯示 Dart: Open DevTools
DevTools
。若是在你的環境變量 PATH
中有 pub
, 能夠運行 🚀:
pub global activate devtools
複製代碼
若是環境變量 PATH
中有 flutter
, 能夠運行 🚀:
flutter pub global activate devtools
複製代碼
下一步,啓動本地 web server
服務來運行開發者工具。運行下面兩個命令中的一個。
pub global run devtools # If you have `pub` on your path.
複製代碼
flutter pub global run devtools # If you have `flutter` on your path.
複製代碼
運行這兩行代碼以後,在命令行應該會有這樣一個輸出:
An Observatory debugger and profiler on iPhone X is available
at: http://127.0.0.1:50976/Swm0bjIe0ks=/
複製代碼
at
後面的就是DevTools
的地址,你們直接用Chrome
打開便可。打開後的網頁須要你填寫一個連接,也就是你須要調試的項目的Debug service
監聽地址,這個地址哪兒來的呢 🤔 ?
3. 啓動一個 app
來 debug
其實上面所需的連接 🔗 地址,就在咱們平時運行項目的Log
中。你們運行工程,在日誌的前幾行就能夠找到Debug service
的地址,就是圖中 listening on
以後的部分,將該連接填入咱們在第二步打開的網頁中,就能夠進入到咱們項目對應的DevTools
之中。
以上三種是Flutter
官網提供的安裝、打開方式,很惋惜,我都沒有打開成功 🤯 ,不是一直安裝,就是打開了一個很是老的版本的DevTools
,應該是和個人Dart SDK
路徑配置有關,因此通過個人研究,發現了一個很是痛快 🤫 的打開方法(目前暫不知有什麼弊端)。
Flutter
文件夾的地址。這個因人而異,各位應該清楚本身電腦上flutter
的路徑吧,好比我就放在我的的development
目錄下:
/Users/tys/development/flutter
複製代碼
DevTools
這就是我這邊要說的暴力打開的關鍵 🔑 ,我發現...,這個DevTools
,好像已經悄悄的放在了Flutter
中。
/Users/tys/development/flutter/.pub-cache/bin/devtools
複製代碼
在上面這個目錄下,你們能夠直接找到它,雙擊點開,直接好傢伙 💡
蕪湖~直接到達上面用命令行打開的最後一步。並且這就是你當前使用的Flutter
版本對應的最新的、可用的DevTools
!
我將按照DevTools頂部工具欄的順序給各位逐個介紹各個功能 🤓 。
1. 瞭解現有佈局。
2. 診斷佈局問題。
有關這個模塊的內容咱們根據下圖中紅色標註的順序一塊兒看一下 🔍
這實際上是一個選擇視圖,你們看到這個Tab
下對應的其實就是你的整個繪製樹 🌲 了,這樣一顆樹的結構複雜度通常都會和你的頁面複雜度相關。若是是一個複雜的頁面結構,這棵樹也會很是龐大,看起來會很模糊,爲了讓咱們能夠更好的看到樹裏面的細節結構,咱們就能夠點擊樹上的某個節點,區查看樹的某一部分的詳細內容 🔮 。
顧名思義,其實這裏就是咱們剛纔所選擇的節點的詳細信息,其實現實的信息真的能夠說很是走心 ❤️ 了。看圖中,我選了一個Container
節點 ,Container
下的未賦值屬性都給你提示出來了,如bg
背景顏色等。若是你的頁面內有顏色、色彩的疊加之類的,經過它能夠看的很清晰 🔬 。
這個就厲害了,是你當前選中節點的佈局瀏覽器。好比你們能夠看到,我選中的這個Container
下面有包裹的詳細結構都有顯示出來,包括各個Wiget
的邊界,甚至給你顯示了計算後的高度和寬度 📏 (按照標準的分辨率尺寸)。
Layout Explorer
不只能讓你查看整個佈局界面,還可讓你作一些簡單的動態操做,讓你在不改動代碼的前提下,明確你的佈局問題,或者缺陷(請看動圖⬇️ )。
點擊該按鈕,將下降你App
內的全部動畫效果的速度,感覺0.5
倍速的神奇世 🤩 ,這裏說的Animations
包括但不只限於你的界面跳轉,Hero
等系統級動畫,我的認爲這部分功能主要有兩個做用
1. 若是在該模式下你的動畫不存在任何卡頓,則說明你的動畫效能很是完美,能夠達到比較好的用戶體驗 👍 。
2. 讓部分動畫製做者看清本身的動畫繪製曲線、路徑 🕳 。
在渲染中添加視覺調試提示,以顯示邊框,填充,對齊和間隔。會在你的模擬器上顯示總體的佈局狀況,這些狀況包括你的總體渲染方向和基礎組件類。
使每一個RenderBox在其每一個文本基線處繪製一條線。就是下圖中的綠線 ⬇️
打開這個功能,你的界面在重繪時,會在重繪的部分更改一個邊界顏色 🎆 。好比,你有一個banner
,間隔1s
換一張圖片,那麼每一秒你的banner
圖周邊的顏色就會變一個隨機顏色。我的感受其目的是讓咱們看到當前頁面正在繪製或重繪的部分。
在進行性能調試時請使用實際設備調試。Skia有兩套很不一樣的後端,Flutter在iOS模擬器中使用純CPU後端,而在實際設備通常使用GPU硬件加速後端,因此性能特性很不同。
TimeLine
是DevTools
中比較實用有實際意義的部分。可讓你實際看到你的APP
存在的UI
問題或GPU
問題。接下來我將帶各位來學習如何去分析本身Flutter APP
的繪製性能 🩺 。
你們首先能夠看到,在上圖中最上層的部分是一個柱形圖 📊 。這部分是你剛纔所作操做的一個繪製狀態圖,根據右邊的圖例,也能明白其中的意思,這邊我再給各位明確一下。
你們看柱狀圖中有紅色有藍色,淡藍色的是UI
線程的繪製狀況、深藍色是你的柵格化線程(GPU
線程)。紅色,表明你的繪製出現了卡頓。通常來講咱們在Flutter
裏咱們定義卡頓:若是一幀的渲染時間超過16ms
,則會被認爲此幀是延時的,爲了達到幀渲染頻率到 60 FPS
(每秒幀數),每一幀的渲染時間必須等於或少於 16 ms
。若是沒有達到這個目標,你會發現 UI
不流暢或丟幀 📌 。
咱們在整個界面的中間部分能夠看到的是Timeline Event
,它其實對應的就是咱們上面繪製狀況圖的細節狀況,是繪製過程當中的事件。咱們利用它能夠詳細的看見咱們卡頓的緣由。咱們挑選其中卡頓的一幀,來仔細分析一下 🧮 。
在下圖中你們能夠看到在Timeline Event
中,依然分爲了兩個部分,上半部分是UI Event
,下半部分是Raster Event
。在這一陣中,咱們能夠明顯的感受到的是,咱們的UI Event
佔用了很是長的時間 ⏰ 。爲了你們能對整個TimeLine Event
的含義有更好的理解,這裏引用了官方的一段解釋:
火焰圖選項卡用於顯示選中幀事件,
CPU
的樣本信息。圖表展現的是自上而下的調用堆棧信息,即上面的堆棧幀調用下面的堆棧幀。每個堆棧幀的寬度表明CPU
執行的時長。棧幀消耗CPU
的時間越長,就越洽有多是咱們進行性能改進的好地方。
咱們在上面的堆棧信息中能夠看到最上層的一個Event
叫VsyncProgressCallback
,在下圖中,咱們能夠在底部看到,這個堆棧的耗時高達40.6ms
,幾乎是沒法接受的🚽 。其實咱們點擊一個流暢的幀後,發現其中也會有VsyncProgressCallback
。那麼爲何這一幀會格外的長,並形成卡頓呢?
所以咱們爲了進一步探究其中的緣由,咱們須要進一步的深刻探究,咱們須要更多的信息。
CPU Flame Chart
) 這裏有你想要的細節信息,包括內部具體某一個堆棧的耗時狀況。爲什麼VsyncProgressCallback
耗時如此之久。內部有哪些細節操做,這裏一清二楚 🐮 。這裏咱們能夠看到,一個長耗時VsyncProgressCallback
相比一個短耗時的VsyncProgressCallback
多了幾個部分。在清楚VsyncProgressCallback
的內部堆棧信息後,咱們就能夠有針對性的再對內部的耗時堆棧進行分析。切換到咱們第二個Tab
。
有關
Flutter
中的Vsync
信號推薦閱讀: Flutter渲染機制 - UI線程 🔗 。
這部分更貼近咱們開發者,咱們能夠詳細看到VsyncProgressCallback
具體調用了哪些函數,哪些函數是耗時比較久的。你們再結合上面一張圖,咱們在卡頓這一幀多作的工做,或者說多調用的函數,就是這裏的performRebuild
,點開函數的具體調用,咱們能夠發現,這個函數一直在循環調用。沒錯這裏的performRebuild
其實就是一個遍歷你繪製樹 🌲 的過程,說明了你在當前幀,更新了一個龐大的繪製樹,而且樹上的多個子節點也進行了從新繪製。因此咱們應該要排查的就是,咱們在界面中的哪一個部分集中調用了多個組件的重繪,或者哪部分的view_mode
,驅動了這樣的一個重繪過程,其中是否有沒必要要的重繪。以此來提升渲染性能 😆 。
上面一部分說明了咱們的UI
線程阻塞的部分緣由,和排查方法,那若是是GPU
呢?一樣,咱們選取了一幀典型的GPU
耗時操做,在這個堆棧信息中咱們能夠看到咱們的GPU
方法確實佔用了大量的時間 ⏳ ,一樣是GPURasterizer::Draw
爲何某一幀會特別久呢?
其實在DevTools
的Raster
視圖中,並不能將這部分展現的很是清晰。可是還有一個辦法能夠深究其緣由。你們能夠直接打開以前填入DevTools
的連接。若是你正在profile
模式下運行,你的log
中就能夠找到這個連接 🔗 。
點開這個連接,在這個頁面的中間部分,咱們能夠找到timeline
工具(我已經在圖中用紅框標出)。
進入這部分timeline
以後,這裏就是最最最最詳細的每一幀的信息了 📌 。你能夠用鼠標選中一塊區域,在下方就會輸出你選中區域的具體函數調用狀況。包括函數名稱、總耗時、調用次數、每次耗時以及一個可視化的柱狀圖 📊 佔比狀況。一目瞭然。有關GPU
部分的函數調用須要各位對Flutter Engine
的源碼有比較高的理解,纔能有針對性的解決問題。其中相關的調用棧很是的複雜。
官方聲明的會大量耗時的skia
函數調用:
saveLayer
: 很是耗時,每次調用須要在CPU裏從新分配一塊繪圖緩衝區,而且告訴GPU
切換繪圖目標。尤爲在比較老的設備上。clipPath
: 耗時,每次調用,會影響接下來每個繪圖指令,當繪圖指令複雜時,會作屢次和clipPath
的相交操做,把在clipPath
以外的部分剔除。
可能你們會說,這部分函數,平時在編程的時候幾乎沒有使用 🤯 ,但其實他們普遍存在於咱們常見的Widget
及其屬性中。好消息是Flutter Team
在過去的更新迭代中已經剔除了很是多的沒必要要的相似上述的耗時操做 🐳 。因此當你們在本身的timeline
中找到相似的耗時操做後,仍是能夠經過一些Widget
的組件源碼去分析找到出處,相較之前容易得多。
在上圖的函數調用狀況圖中,短耗時的操做不表明其沒有可能形成卡頓。有可能你找到了
saveLayer
的調用,但沒有想象中的耗時。實際是由於:Skia的GPU的後端在接收到saveLayer
的指令後會進行一個簡單的預處理,就當即返回,形成不耗時的假象。但實際後續異步的過程當中還會調用SkCanvas::Flush
形成大量耗時。這裏異步處理的目的是將多條預處理消息打包 📦 送至GPU
進行繪製。
有關Flutter
中的界面繪製性能相關就介紹到這裏了,但願這篇文章能給各位起到必定的幫助做用 🤪 ,後續會繼續介紹Flutter
相關的內存管理和其餘相關知識,敬請期待 🧸 。
參考:DevTools