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