前端性能優化 — 保姆級 Performance 工具使用指南
性能分析一直是前端er們津津樂道的話題;而俗話說得好:工欲善其事,必先利其器;
說到前端性能,就少不了性能分析的利器 —— Performance ??;我想各位前端小伙伴,在使用 Chrome 瀏覽器 DevTool
時或多或少都有留意到這個面板吧?
圖片
今天我們就邁開性能分析的第一步,來探究一下 Performance 這個強大的工具。
文章中提到的 Performance 面板,以 Chrome 118 版本為參考。
Performance 面板
我們打開 Performance 面板:
圖片
我把 Performance 面板大概劃分為操作區、設置區、報告區三塊區域:
- 操作區:主要用于性能分析的開啟、關閉、性能報告的上傳下載等;
- 設置區:用于設置性能數據分析期間的各項指標,比如:CPU 運算能力、網絡狀態等等;
- 報告區:顧名思義,就是呈現最終性能分析報告的地方。
下面我們先來一起看看操作區的內容。
操作區
觀察下圖中用紅線框起來的部分,這里有幾個按鈕:
圖片
錄制報告
按鈕與
的功能大致相同,都是用于記錄頁面性能數據;
兩個按鈕點擊后都會出現下面這樣的彈窗:
圖片
image.png
不過需要注意的是,這兩種錄制方式之間有一些不同:
- 點擊
(Record) 按鈕,Chrome 會開始記錄交互階段的性能數據,需要手動點擊 Stop 停止錄制;
- 而點擊
(Start Profiling and reload page) 按鈕,Chrome 會重新刷新頁面并自動開始記錄,等到頁面完全渲染出來后自動結束記錄。
清除報告
錄制完成的數據,如果我們不需要了,就可以點擊(Clear) 按鈕來清除數據;
是不是很一目了然呢?
上傳/下載報告
當我們的數據錄制完成,就可以 點擊(Save Profile) 按鈕來將錄制的報告下載保存在本地;
有了下載,當然少不了它的好兄弟上傳!
點擊(Load Profile) 就可以將本地報告再次上傳到 Performance 面板中;
報告對比
實際上,我們每次錄制的報告都被自動留存起來;
當存在多份性能報告時,還可以通過下拉切換查看不同的報告:
圖片
這樣就能很方便地對比不同時間段的性能報告。
圖中用紅虛線框起來的部分,就是用于切換報告的下拉框。
Screenshots 和 Memory
在操作區的右邊還有兩個復選框,Screenshots 和 Memory:
圖片
Screenshots
當勾選 Screenshots 后,在生成的性能報告中就會多出一欄用于記錄頁面在加載過程中的每一幀的視覺變化,并生成一系列快照;
并且當鼠標 hover 在這個區域時,就可以查看當前幀的快照:
圖片
通過查看這些快照,我們就可以了解頁面在不同時間點的渲染情況。
Memory
而 Memory 功能則是用于觀察頁面的內存使用情況隨時間的變化。
當勾選 Memory 功能后,在性能報告中就會顯示頁面的總內存使用量、堆內存使用量以及各種 JavaScript 對象的內存分配情況:
圖片
同樣,當鼠標 hover 在下方不同類型文件占據內存情況的折線圖時,就可以查看當前時間點下這些文件使用內存的情況。
垃圾回收
最后,操作區的(Collect garbage) 按鈕用于手動觸發 JavaScript 垃圾回收。
圖片
image.png
當我們在進行性能測試時,就可以在特定的時間點手動觸發垃圾回收,以確保測試結果的準確性。
設置區
在文章前面簡單介紹過,設置區主要用于設置性能數據分析期間的各項指標;
下面我們來看看具體可以做哪些設置:
圖片
Disable JavaScript samples
默認情況下,Chrome 在做性能分析采樣時會記錄當前 JavaScript 執行的堆棧信息,并在報告區的 Main 部分呈現出來:
如果我們不關注 JavaScript 執行相關的性能,比如:測試在不同網絡情況下的代碼執行性能、測試渲染性能時;
這種情況下就可以勾選 Disable JavaScript samples 這個選項,從而提高性能分析的效率;
未勾選 Disable JavaScript samples 的情況下,報告區記錄了 JavaScript 執行時的堆棧信息 (圖中紅線框起的部分) :
圖片
勾選了 Disable JavaScript samples 的情況下,報告區只記錄了一些高級事件,比如:Function Call、渲染相關事件等:
圖片
Enable advanced paint instrumentation
這個選項用于啟用高級繪制儀器;當你勾選了這個選項后,Chrome 將記錄更詳細的繪制信息,包括每個繪制操作的時間、持續時間、繪制區域等。
勾選了 Enable advanced paint instrumentation 后,當鼠標選中報告中 Frames 數據的某一幀時,在下方的面板里就會多出一個 Layers 的選項;
圖片
我們知道,瀏覽器在渲染一個頁面時會有針對性的對一些效果進行分層,而 Layers 的選項下展示的正是頁面的圖層樹信息:
圖片
通過觀察這些繪制操作的時間和持續時間,就能判斷哪些繪制操作占用了較長的時間,可能導致頁面渲染緩慢對癥下藥。
CPU 和 Network
在 CPU 下拉選項中,我們可以通過降低 CPU 的性能,來模擬低性能設備上的頁面運行情況;比如移動設備,或者一些比較老舊的計算機;
而 Network 下拉框可以選擇不同的網絡條件,用于模擬網絡不佳的情況下頁面的運行情況。
Hardware concurrency
hardware concurrency 選項用于模擬硬件并發性能;勾選這個選項后,我們就可以選擇從 1 到最大硬件并發性能水平之間的值,以模擬不同的硬件環境。
通過切換不同的 hardware concurrency 值,可以觀察頁面在不同硬件并發性能水平下的性能表現;這對于優化頁面的并發處理和多線程任務非常有幫助。
硬件并發性能是指處理器(CPU)同時執行多個線程或任務的能力。現代計算機通常具有多核處理器,每個核心都可以同時執行多個線程。硬件并發性能的提高可以顯著提升計算機的性能和響應能力。
報告區
接下來就是我們的重頭戲,最終性能分析報告呈現的區域;我們之前介紹的操作、設置最終都是為性能報告服務。
我們以掘金首頁為例,來看看報告區都有哪些內容。
首先,我們要打開谷歌瀏覽器的無痕模式;默認快捷鍵是 Command+Option+N (Mac) 或者 Control+Shift+N (Windows, Linux);
然后打開 掘金首頁[1],點擊(Start Profiling and reload page) 按鈕來進行錄制;
等待幾秒鐘后,一份完整的性能報告就呈現出來啦:
圖片
從上圖中可以看出,這份性能報告大概可以分為兩塊區域:概覽區、性能報告區。
而所有的這些性能指標都是基于時間的維度來展示的,因此在性能報告中還有一條貫穿整個報告的時間線。
使用無痕模式是為了避免安裝的一些插件對性能測試產生影響。
概覽區
首先,概覽區的 x 軸就是時間線,而 y 軸展示了幾個關鍵指標:CPU 占用情況、NET 網絡請求情況、HEAP 堆內存使用量等;如果勾選了 Screenshots 還會有每一幀的繪制快照。
這些指標會以時間為順序,通過圖表的形式展現出來。
當我們用鼠標點擊這個區域,在下方的性能報告和詳情信息區域,就會呈現這一時間區間的性能情況:
圖片
同時,還支持通過多種方式改變時間區間的長度:
- 滾動鼠標滾輪;
- 按住鼠標左鍵拖動;
- 拖拽滑塊時間區間兩邊的滑塊;
- 鍵盤上的 w 鍵和 s 鍵。
而使用鍵盤上的 a 鍵和 d 鍵則可以在固定時間區間長度的同時,精確修改時間區間的作用范圍。
性能報告區
這個區域呈現了許多性能指標項,我們一起來看看吧。
Network
Network 部分展現的是網絡請求的瀑布圖,我們點擊圖標就可以展開這個面板:
圖片
請求的文件類型
從圖中可以看出,這些網絡請求的瀑布圖有許多種顏色,這些顏色就代表了請求對應的文件類型:
藍色: 請求 HTML 文檔;
紫色:請求 CSS 文件;
黃色: 請求 JS 文件;
綠色: 請求圖片;
請求時長的構成
不知道小伙伴們有沒有注意到,瀑布圖中的每個請求都被分為了四個部分:左側的線條、中間淺色的條形圖形、中間深色的條形圖以及右側的線條;
這些劃分又有什么含義呢?
- 左側的線:我們知道,在發送一個網絡請求前,需要先解析 URL、建立連接等一系列操作;而左側的線代表了 請求的開始,直到 Connection Start 事件組相關事件結束(包括 Connection Start 事件) ;
- 中間的淺色部分條形圖代表了 Request Sent 和 Waiting (TTFB,即 Time To First Byte) 的時間;TTFB 是指從發送請求到接收到第一個字節的時間,它表示了服務器響應的延遲時間。
- 中間的深色部分條形圖代表了從接收到第一個字節到請求的所有內容都被下載完成的時間。
- 最后右側的線代表了主線程等待的時間。
圖片
請求的優先級
仔細觀察每個請求,會發現請求左上角有個小小的方塊,這個方塊代表了本次請求的優先級。
深藍色的方塊表示本次請求優先級更高;而淺藍色方塊表示優先級較低。
圖片
請求的詳細信息
接下來,我們點擊其中一個網絡請求,可以看到下方的面板展示了請求的詳情信息,包括請求時間、請求方法、優先級等等:
圖片
Frames
Frames 區域展示了繪制一個幀所花費的確切時間;在這個部分,同樣用顏色來區分了四種類型的幀:
- 空閑幀(白色):表示在該幀中沒有發生任何渲染或更新。
- 正常幀(綠色
):表示該幀在適當的時間內被渲染出來,沒有出現延遲或問題。
- 部分呈現幀(黃色,帶有稀疏的寬虛線圖案
):表示 Chrome 盡力在適當的時間內渲染了部分視覺更新。例如:渲染器進程的主線程的工作延遲了,但合成器線程(如滾動)按時完成了渲染,則會出現這種情況。
- 丟幀(紅色,帶有密集的實線圖案
):表示該幀由于性能問題或其他原因導致延遲,無法按時渲染。
Timings
Timings 這個模塊展示了衡量網頁性能(FP、FCP、DCL、LCP、L)的幾個關鍵指標,以及完成指標對應的時間:
圖片
我們來看看這些指標都代表什么含義:
FP (First Paint)
指頁面的首次渲染的時間點。在完成首次渲染之前,用戶看到的都是 沒有任何內容的白色頁面,也就是我們常說的 白屏時間。
FP 可以反映頁面加載的整體速度。
FCP (First Contentful Paint)
指頁面的首個內容繪制時間,即瀏覽器在頁面上繪制出第一塊有實際內容的區域(如文本、圖像等)的時間點。
FCP 反映了用戶可以看到有意義的內容的時間。
DCL (DOM Content Loaded)
指當 HTML 文檔被完全加載和解析后,DOM 樹構建完成并且所有關聯資源(如樣式表、腳本等)已經下載完成,觸發 DOMContentLoaded 事件的時間點。
DCL 反映了頁面的可交互性,表示頁面已經準備好響應用戶的操作。
LCP (Largest Contentful Paint)
指頁面上最大的一個可見元素(如圖片、文本等)繪制完成的時間點。
LCP 是衡量頁面加載速度的重要指標,它反映了頁面主要內容的加載完成時間。
L (Load)
指頁面完全加載完成的時間點。包括所有資源(如圖片、樣式表、腳本等)都已下載完成,并且相關的 DOM、CSSOM 和 JavaScript 都已經處理完成。
L 反映了整個頁面加載的時間。
Layout Shifts
這個指標用于衡量 頁面加載過程中發生的視覺不穩定性。
那么什么叫做視覺不穩定性呢?
實際上,當用戶在頁面加載期間進行交互時,如果頁面中的元素發生意外的移動或調整,會導致頁面上的元素重新排列,從而造成視覺上的不連續和不穩定感。
這種 元素的移動可能會干擾用戶的操作,例如點擊了一個不想點到的按鈕,或者導致誤觸其他元素。
我們點擊 Layout Shifts 區域的色具體色塊,在下方的 Summary 一欄就會展示此次位移的具體信息:
圖片
Main
這項指標可謂是整個性能報告中的重點區域,其中展示了 主線程在進行的相關活動。
火焰圖
Main 指標中圖表的這種展現方式稱為火焰圖;而堆疊組成火焰圖的這些彩色矩形,則代表一個個函數調用堆棧:
圖片
矩形顏色
與 Network 用固定顏色來區分請求類型不同,Main 指標中的顏色是隨機分配的。
但是來自同一個腳本的調用在記錄中會被分配為相同的顏色。
長任務
小伙伴們可能已經留意到了,在有的 Task 中除了灰色的區域外,還有部分被紅色密集實線覆蓋,同時右上角還有一個紅色的三角 :
圖片
這實際上是用來標識這個任務是個長任務。
執行時長超過 50 毫秒的任務會被定義為長任務;而超過 50 毫秒的部分就會用這種紅色密集實線覆蓋。
這些長任務可能會阻塞主線程,導致頁面卡頓、無法及時響應用戶輸入等等;是我們需要 重點關注 的對象。
矩形堆疊邏輯
圖中位于最上方的 Task 表示 一個由瀏覽器調度和執行的任務單元;Task 的 長度就表示這個任務執行時間的跨度。
而 Task 下方的這些矩形是根據函數之間的調用關系來堆放的,比如 ——
上圖中,一個指針事件 pointermove 的觸發,導致了一個 (匿名函數調用(Function Call) ;而這個匿名函數調用又引起了 value 函數的調用...以此類推一直到最后的函數 n。
任務具體信息
下面我們來查看一下對應任務的具體信息。
當我們選中任意一個任務時,下方的面板就會展現對應的信息:
圖片
Summary
Summary 選項卡展示了 當前任務的具體信息,包括長任務警告、總任務時長、各個子任務耗時等等:
圖片
Bottom-Up
Bottom-Up 選項卡將當前任務下所有活動都展示出來,并且根據時間進行倒序排序。
這樣一來,一眼就能看出是哪個活動耗費了較長的時間:
圖片
并且還貼心的提供了篩選 (Filter) 功能和分組 (Grouping) 功能,方便我們分類查看:
image.png
圖中可以看出,整個圖表分為三列:
- Self Time 表示這個根活動自身花費的時間;
- Total Time 表示這個根活動自身以及導致的子活動花費的時間總和。
- Activity 就是對應的活動名稱;并且點擊活動名稱右側的鏈接,還可以直接跳轉到對應的源碼。
圖片
Call Tree
Call Tree 選項卡可以用來查看當前任務下的根活動,以及根活動引發的一系列子活動的耗時。
圖片
根活動是那些導致瀏覽器做一些工作的活動。比如前面提到的 pointermove ,瀏覽器會觸發一個Event活動作為根活動,該事件可能導致處理程序執行,依此類推。
可以簡單理解為火焰圖頂層的活動。
Event Log
最后的 Event Log 選項卡是按照活動在記錄過程中發生的先后順序來呈現表格的:
圖片
這里的下拉不是用來做分組 (Grouping) 的,而是以時間為維度來過濾濾掉耗時少于 1 毫秒或 15 毫秒的活動:
圖片
而旁邊 Loading、Scripting、Rending、Painting 這些復選框,是用于通過類型來過濾表格中的數據:
圖片
并且這里的表格多了一列 Start Time;顧名思義就是對應活動的開始時間。
其余部分
報告區中剩余的信息,比如 ——
- GPU:展示了 GPU 的活動情況;
- Compositor:展示了合成線程的活動情況;
這些都大同小異,在這里就不一一展開講啦,留給大家自己去探索。