摘要:本文給你們簡單介紹瞭如何生成網站的性能分析報告。html
本文分享自華爲雲社區《在瀑布下用火焰烤餅:三步法助你快速定位網站性能問題》,原文做者:Kagol 。前端
性能,是一個問題。chrome
每一個項目成長到必定的規模,都幾乎必然要遇到性能問題,當遇到性能問題時,咱們是:瀏覽器
一臉懵逼,就知道很卡、很慢,不知道爲何,性能優化
仍是,服務器
可以快速洞察性能瓶頸,找到行之有效的優化方案。markdown
取決於咱們對性能的理解深淺,以及是否有一套好的工具和方法。網絡
接下來給你們分享我本身在定位業務性能問題時經常使用的三步法,爲了方便記憶,我把它總結爲一句話:在瀑布下用火焰烤餅。函數
話很少說,喝口水直接開擼!工具
介紹三步法以前,先來簡單瞭解下Chrome開發者工具的Performance性能面板,以及性能分析報告的基本組成。
以DevUI團隊的掘金我的主頁爲例,使用Chrome瀏覽器訪問:juejin.cn/user/712139…
而後按F12打開Chrome的開發者工具,選擇Performance性能面板。
這時咱們會看到一個簡單的指引:
指引裏面有兩個按鈕,上面的按鈕是手動錄製,下面的是自動錄製,咱們點擊傻瓜式的自動錄製,自動錄製會自動刷新頁面,在頁面加載完成以後,生成該頁面的性能分析報告,無需人工干預,很是方便。
等個幾秒鐘報告就生成好了,一眼看去,花花綠綠的,不知道從何看起?
咱們對生成的性能分析報告作一個簡單的面板分類,看起來就很清晰了。
性能報告的頂部是一個工具欄(或者叫控制面板),裏面有一堆按鈕,我這邊用得比較多的是前面三個,其中前兩個在指引裏已經介紹過了,第三個是用來清除報告的。
還有兩個隱藏的功能也頗有用,一個是模擬慢網速的,另外一個是模擬慢CPU的,對移動端應用作性能優化可能會用到。
工具欄下面是一個概覽面板,顯示了整個頁面加載過程當中的FPS(Frames Per Second,每秒傳輸幀數),用來評估頁面的流暢度,有大片紅色說明頁面可能存在卡頓。
FPS下面是CPU處理各個任務花費的時間,再往下是網絡請求的耗時,概覽面板最下面是每一幀的截圖。
概覽面板往下是線程面板,默認展開的是網絡請求瀑布圖,其餘線程的詳情都是收起的。
每一個線程面板對性能分析都有價值,而我最經常使用的是瀑布圖和火焰圖,後面會重點分析這兩個圖,如何利用這兩張圖來分析網站的性能瓶頸。
再往下是內存面板,內存面板須要在控制面板中手動打開,它是一個分類的內存佔用折線圖。
每條折線是一種任務隨時間推移的內存佔用:
最下面是詳情面板,首先看到的是一個餅圖,這個餅圖顯示了各類類型任務的佔比,這個很是有用,可否一眼看出什麼類型的任務是性能瓶頸。
是資源加載仍是腳本執行?是頁面渲染仍是圖像繪製?又或者是空閒時間太長?
剛纔介紹Performance面板的組成時,提到了3個很是有用的性能分析利器,分別是詳情餅圖、請求瀑布圖和主線程火焰圖。
我把這三張圖總結成一句話:在瀑布下用火焰烤餅
這句話也是我本身在作性能分析和優化時,屢試不爽的小技巧。
詳情面板中的餅圖用於展現各類類型任務的耗時佔比。
主要有如下幾種任務:
仍是舉剛纔的例子。
從餅圖能夠看出佔比最多的是腳本執行和空閒。
腳本執行時間長,咱們大概能夠猜想裏面可能存在長任務(Long task);
而空閒佔比多多是等待服務器的響應時間太長。
餅圖能夠快速造成基本的判斷,而具體緣由則須要分析瀑布圖和火焰圖。
咱們來看下請求瀑布圖,瀑布圖和火焰圖都是線程面板的一部分,瀑布圖的橫軸是時間軸,瀑布圖上有不少五光十色的色塊,這些色塊就是請求塊,每種顏色表明一類資源:
咱們主要關注那些長色塊,長色塊意味着耗時長,多是性能瓶頸。
仍是看下掘金我的主頁的瀑布圖。
咱們先觀察這張圖有什麼特色,圖形觀察能力,相信你們小學就已經培養起來了,大體咱們能夠總結出如下比較明顯的特色:
相似的特色咱們還能夠總結出不少來,可是這些特色說明了什麼呢?可否幫助咱們定位性能瓶頸呢?
回答這些問題須要咱們對瀑布圖以及瀏覽器原理有不少的認識,咱們一步步來分析吧。
咱們按從左到右,從上到下的順序進行分析,最左邊有兩個色塊,一個灰色色塊,一個藍色色塊,咱們分別點擊這兩個色塊,在詳情面板看下它們的詳情信息。
先看灰色色塊
咱們有注意到這個請求的啓動器(Initiator)是一個Chrome插件:chrome://new-tab-page/omnibox.mojom-lite.js
所以咱們不關注,接着看藍色色塊
前面咱們已經介紹了,藍色色塊表明HTML文件,咱們從詳情的Mime Type爲text/html也能夠驗證這一點。
咱們滾動鼠標滾輪,把這個瀑布圖放大,看這個藍色請求塊的細節
經過查看細節圖,咱們有了新的發現:
每一個請求塊都由四部分組成:
這個HTML文件是整個網頁渲染的起點,成功請求並下載這個文件,纔會有接下來的故事。
這個請求塊的淺色塊部分佔比比較大,根據前面的介紹,淺色部分表明的是服務器的響應速度,瀏覽器已經早早地發出了請求,服務器卻遲遲纔給迴應(第一個字節到達瀏覽器)。
中間多是網絡慢,也多是服務器處理速度慢,須要具體排查,畢竟這個HTML文件不算大,才111KBb,卻花了179ms。
對比另一個文件layouts.default.js,體積比它大124KB,請求耗時卻比它小一半多,才74ms。(後來發現這個數據不穩定,這個HTML文件應該不至於構成性能瓶頸)
另外全部後續的請求都依賴於這個HTML,沒有它其餘請求都不會發生,它是一個阻塞請求,性能必需要有保障。
咱們繼續看右邊的請求塊,頂部那個超長的灰色塊依然是Chrome插件的請求,咱們無論,看下面那一堆黃色的請求塊,這些都是JavaScript文件。
HTML文件下載完了以後,就會開始一行一行解析其中的HTML標籤,遇到設置了誰、src屬性的
從瀑布圖能夠看出,一共並行下載了8個JavaScript文件,它們的域名都是同樣的:
sf1-scmcdn2-tos.pstatp.com
不是說Chrome瀏覽器對同一個域名,並行的請求數最大是6個嗎?
不只僅是JavaScript文件,下面還有3個同域名的圖片資源,也是在並行請求的,也就是說幾乎同時發起了11個請求。
這說明掘金的靜態資源服務器升級到了HTTP/2
HTTP/2的多路複用能夠實現一個TCP鏈接同時傳輸多個資源。
咱們到Network面板裏去看下這些JavaScript的請求詳情,果真和咱們猜想的一致,這一點必須給掘金點個贊👍
發一個某86網站和掘金的對比圖,你們感覺一下某86網站:
掘金:
雖然前者更像一個瀑布,可是我喜歡後者絲滑般的體驗。
咱們再來仔細看這8個請求,相信細緻的你必定發現了一個現象:
請求塊的左右線都很是短是一個好現象,說明沒有什麼等待時間,全部時間都用在了傳輸數據上。
咱們分別點擊1/5/8請求塊看它們的詳情
請求塊詳情1大小:4KB
耗時:635ms5大小:90KB
耗時:635ms8大小:3.9MB
耗時:633ms
這很是奇怪,1/5的資源大小和8的不在一個量級上,耗時卻比8還多。
爲了肯定這是偶然的,仍是必然的,我又錄製了兩次這個掘金我的主頁的性能報告
此次和預期的基本一致,8耗時比其餘都長,這個JavaScript文件3.9MB,太大了,極可能是性能瓶頸。
讓咱們繼續往下分析,黃色JavaScript色塊下面一共有三種顏色的色塊:
這幾個文件體積都不大,而且經過屢次生成性能報告,發現這幾個請求耗時都不如第8個JavaScript文件長,因此初步判斷這些請求不構成性能瓶頸。
接着看中間那個瀑布,經過屢次生成性能報告,發現中間瀑布並無什麼特別耗時的請求,不過無論生成多少次報告,有一點是肯定的,就是這三個瀑布之間老是有些空白
這些空白到底說明了什麼呢?
看完火焰圖,相信你就會豁然開朗。
在看正式的火焰圖以前,先來看一個瀑布圖和火焰圖放在一塊兒的效果
看完這張瀑布和火焰的對比圖,你必定看出了一個現象
瀑布圖有空白的地方,火焰圖就有顏色;
瀑布圖有顏色的地方,火焰圖就是空白。
But Why?
要回答這個問題須要瞭解瀏覽器主線程執行任務的原理,以及火焰圖是作什麼的,彆着急,讓咱們一步步來分析。
火焰圖也是線程面板的一部分,它表明的是瀏覽器主線程的任務流:
隨着頁面的加載,時間的推移,主線程依次作了什麼事兒
火焰圖的橫軸是時間,縱軸是一個個的宏任務。
每一個宏任務下面若干個微任務,每一個微任務下面有可能有不少子任務,依次類推。
因爲有些任務的嵌套層級深,有些嵌套層級淺,因此呈現倒立的火焰狀。
每種類型的任務顏色都不同(無需記憶,有個大體的印象便可):
仍是先大概看下掘金我的主頁的火焰圖
而後用咱們小學就學會的看圖找規律的技能,找到這個圖有什麼特色,大體掃一眼,咱們就能總結出至少如下幾個特色:
多花點時間,可能咱們還能有更多的發現,不過這幾個是最顯而易見的。
爲了回答這些問題,咱們須要近距離觀察下火焰圖。
既然火焰圖表明主線程每一個時間點都在幹嗎,那麼空白天然就意味着主線程沒在幹活,那麼,它在幹嗎呢?
它在等待,等待什麼呢?
等待服務器返回一些必要的資源和數據
因此火焰圖的空白處都是瀏覽器在等待服務器返回數據
在全部主線程執行的任務中,咱們尤爲須要關注的是那些耗時特別長的長任務(Long task),這些長任務的特色前面已經說了:
背景色是紅色的陰影線
右上角有一個紅色的小三角形
三個長任務1s鍾就找到了
接下來是分析長任務,找到耗時長的具體模塊/組件/方法。
咱們把最右邊最大的那個火焰放大,看看裏面到底有些什麼祕密。
放大以後,咱們很快就發現這個耗時591ms的長任務,有90%的時間都花費在了一個叫init的方法上,這個方法一共執行了6次,其中3/4/6耗時尤爲長
第n個init方法詳情3耗時:197ms4耗時:93ms6耗時:111ms
這個init方法究竟是作什麼的呢?
多是掛在Vue組件的,會不會是有些組件特別大,裏面的邏輯太複雜,這裏須要掘金的前端給出答案。
再看下左邊那個第二大的火焰,一樣滾動鼠標滾輪把它放大
咱們發現其中有一個forEach循環特別耗時,這個循環好像在計算什麼東西,一共花了150ms。
這個依然須要看下具體的源碼才能找到問題的根因。
最後給你們分享下我本身以前在XBoard看板項目中,經過火焰圖發現一個依賴庫的性能問題。
也是遵循同樣的思路:
當時XBoard看板頁有一堆長任務,我找了其中的TOP3
而後將第一個長任務放大,很快就有了收穫,我發現其中有一個叫drawQrCode的方法耗時比較長,一共花了192ms。
接着經過查看詳情,發現這是一個依賴庫的方法,該依賴庫定義了一個drawQrCode用來繪製二維碼,而這個二維碼其實不在看板頁面上,而是須要經過鼠標hover到某個按鈕上才加載出來。
因此當時解決的方案就是延遲drawQrCode方法的執行,即:
首頁加載時,不執行drawQrCode方法,當鼠標移到相應按鈕上時,才執行。
瀑布圖和火焰圖是相互補充、相互驗證的關係。
瀑布圖表明瀏覽器發起向服務器的請求,而後瀏覽器根據服務器返回的數據,經過腳本執行相應的邏輯和頁面的渲染。
當瀑布圖有請求塊時,說明瀏覽器在向服務器請求數據,若是瀏覽器必須依賴這些數據來作下一步的頁面渲染,那麼在服務器返回數據以前,極可能瀏覽器就沒事幹,而後火焰圖上出現空白,餅圖也會出現空閒(Idle)。
當瀏覽器拿到服務器返回的數據時,主線程正在處理這些數據,並渲染頁面,所以極可能就無法向服務器發請求,這時瀑布圖就會出現空白。
因此
發現瀑布圖出現空白,極可能存在長任務,須要找到具體的耗時方法,並進行優化
發現火焰圖出現空白,極可能是某些後臺接口慢或者存在超大靜態資源,須要定位到慢的緣由,並想辦法優化
本文先給你們簡單介紹瞭如何生成網站的性能分析報告,以及這份報告的大體組成;
接着跟你們分享我本身在定位業務性能問題時,常用的三步法:在瀑布下用火焰烤餅;
從餅圖中咱們能夠對網站的性能有一個大體的認識,從瀑布圖快速地發現慢接口和大資源,而從火焰圖中,咱們能夠細緻地洞察到具體哪一個模塊/哪一個組件/哪一個方法可能成爲性能瓶頸。