性能監測是前端性能優化的重要一環。監測的目的是為了確定性能瓶頸,從而有的放矢地開展具體的優化工作。
平時我們比較推崇的性能監測方案主要有兩種:**可視化方案、可編程方案**。這兩種方案下都有非常優秀、且觸手可及的相關工具供大家選擇,本節我們就一起來研究一下這些工具的用法。
## 可視化監測:從 Performance 面板說起
Performance 是 Chrome 提供給我們的開發者工具,用于記錄和分析我們的應用在運行時的所有活動。它呈現的數據具有實時性、多維度的特點,可以幫助我們很好地定位性能問題。
### 開始記錄
右鍵打開開發者工具,選中我們的 Performance 面板:

當我們選中圖中所標示的實心圓按鈕,Performance 會開始幫我們記錄我們后續的交互操作;當我們選中圓箭頭按鈕,Performance 會將頁面重新加載,計算加載過程中的性能表現。
tips:使用 Performance 工具時,為了規避其它 Chrome 插件對頁面的性能影響,我們最好在無痕模式下打開頁面:


### 簡要分析
這里我打開掘金首頁,選中 Performance 面板中的圓箭頭,來看一下頁面加載過程中的性能表現:

從上到下,依次為概述面板、詳情面板。下我們先來觀察一下概述面板,了解頁面的基本表現:

我們看右上角的三個欄目:FPS、CPU 和 NET。
**FPS**:這是一個和動畫性能密切相關的指標,它表示每一秒的幀數。圖中綠色柱狀越高表示幀率越高,體驗就越流暢。若出現紅色塊,則代表長時間幀,很可能會出現卡頓。圖中以綠色為主,偶爾出現紅塊,說明網頁性能并不糟糕,但仍有可優化的空間。
**CPU**:表示CPU的使用情況,不同的顏色片段代表著消耗CPU資源的不同事件類型。這部分的圖像和下文詳情面板中的Summary內容有對應關系,我們可以結合這兩者挖掘性能瓶頸。
**NET**:粗略的展示了各請求的耗時與前后順序。這個指標一般來說幫助不大。
### 挖掘性能瓶頸
詳情面板中的內容有很多。但一般來說,我們會主要去看 Main 欄目下的火焰圖和 Summary 提供給我們的餅圖——這兩者和概述面板中的 CPU 一欄結合,可以幫我們迅速定位性能瓶頸(如下圖)。

先看 CPU 圖表和 Summary 餅圖。CPU 圖表中,我們可以根據顏色填充的飽滿程度,確定 CPU 的忙閑,進而了解該頁面的總的任務量。而 Summary 餅圖則以一種直觀的方式告訴了我們,哪個類型的任務最耗時(從本例來看是腳本執行過程)。這樣我們在優化的時候,就可以抓到“主要矛盾”,進而有的放矢地開展后續的工作了。
再看 Main 提供給我們的火焰圖。這個火焰圖非常關鍵,它展示了整個運行時主進程所做的每一件事情(包括加載、腳本運行、渲染、布局、繪制等)。x 軸表示隨時間的記錄。每個長條就代表一個活動。更寬的條形意味著事件需要更長時間。y 軸表示調用堆棧,我們可以看到事件是相互堆疊的,上層的事件觸發了下層的事件。
CPU 圖標和 Summary 圖都是按照“類型”給我們提供性能信息,而 Main 火焰圖則將粒度細化到了每一個函數的調用。到底是從哪個過程開始出問題、是哪個函數拖了后腿、又是哪個事件觸發了這個函數,這些具體的、細致的問題都將在 Main 火焰圖中得到解答。
## 可視化監測: 更加聰明的 LightHouse
Performance 無疑可以為我們提供很多有價值的信息,但它的展示作用大于分析作用。它要求使用者對工具本身及其所展示的信息有充分的理解,能夠將晦澀的數據“翻譯”成具體的性能問題。
程序員們許了個愿:如果工具能幫助我們把頁面的問題也分析出來就好了!上帝聽到了這個愿望,于是給了我們 LightHouse:

> Lighthouse 是一個開源的自動化工具,用于改進網絡應用的質量。 你可以將其作為一個 Chrome 擴展程序運行,或從命令行運行。 為Lighthouse 提供一個需要審查的網址,它將針對此頁面運行一連串的測試,然后生成一個有關頁面性能的報告。
敲黑板劃重點:它生成的是一個報告!Report!不是干巴巴地數據,而是一個通過測試與分析呈現出來的結果(它甚至會給你的頁面跑一個分數出來)。這個東西看起來也真是太贊了,我們這就來體驗一下!
首先在 Chrome 的應用商店里下載一個 LightHouse。這一步 OK 之后,我們瀏覽器右上角會出現一個小小的燈塔 ICON。打開我們需要測試的那個頁面,點擊這個 ICON,喚起如下的面板:

然后點擊“Generate report”按鈕,只需靜候數秒,LightHouse 就會為我們輸出一個完美的性能報告。
這里我拿掘金小冊首頁“開刀”:

稍事片刻,Report 便輸出成功了,LightHouse 默認會幫我們打開一個新的標簽頁來展示報告內容。報告內容非常豐富,首先我們看到的是整體的跑分情況:

上述分別是頁面性能、PWA(漸進式 Web 應用)、可訪問性(無障礙)、最佳實踐、SEO 五項指標的跑分。孰強孰弱,我們一看便知。
向下拉動 Report 頁,我們還可以看到每一個指標的細化評估:

在“Opportunities”中,LightHouse 甚至針對我們的性能問題給出了可行的建議、以及每一項優化操作預期會幫我們節省的時間。這份報告的可操作性是很強的——我們只需要對著 LightHouse 給出的建議,一條一條地去嘗試,就可以看到自己的頁面,在一秒一秒地變快。
除了直接下載,我們還可以通過命令行使用 LightHouse:
```
npm install -g lighthouse
lighthouse https://juejin.im/books
```
同樣可以得到掘金小冊的性能報告。
此外,從 Chrome 60 開始,DevTools 中直接加入了基于 LightHouse 的 Audits 面板:

LightHouse 因此變得更加觸手可及了,這一操作也足以證明 Chrome 團隊對 LightHouse 的推崇。
## 可編程的性能上報方案: W3C 性能 API
W3C 規范為我們提供了 Performance 相關的接口。它允許我們獲取到用戶訪問一個頁面的每個階段的精確時間,從而對性能進行分析。我們可以將其理解為 Performance 面板的進一步細化與可編程化。
當下的前端世界里,數據可視化的概念已經被炒得非常熱了,Performance 面板就是數據可視化的典范。那么為什么要把已經可視化的數據再掏出來處理一遍呢?這是因為,需要這些數據的人不止我們前端——很多情況下,后端也需要我們提供性能信息的上報。此外,Performance 提供的可視化結果并不一定能夠滿足我們實際的業務需求,只有拿到了真實的數據,我們才可以對它進行二次處理,去做一個更加深層次的可視化。
在這種需求背景下,我們就不得不祭出 Performance API了。
### 訪問 performance 對象
performance 是一個全局對象。我們在控制臺里輸入 window.performance,就可一窺其全貌:

### 關鍵時間節點
在 performance 的 timing 屬性中,我們可以查看到如下的時間戳:

這些時間戳與頁面整個加載流程中的關鍵時間節點有著一一對應的關系:

通過求兩個時間點之間的差值,我們可以得出某個過程花費的時間,舉個??:
```
const timing = window.performance.timing
// DNS查詢耗時
timing.domainLookupEnd - timing.domainLookupStart
// TCP連接耗時
timing.connectEnd - timing.connectStart
// 內容加載耗時
timing.responseEnd - timing.requestStart
···
```
除了這些常見的耗時情況,我們更應該去關注一些**關鍵性能指標**:firstbyte、fpt、tti、ready 和 load 時間。這些指標數據與真實的用戶體驗息息相關,是我們日常業務性能監測中不可或缺的一部分:
```
// firstbyte:首包時間
timing.responseStart – timing.domainLookupStart
// fpt:First Paint Time, 首次渲染時間 / 白屏時間
timing.responseEnd – timing.fetchStart
// tti:Time to Interact,首次可交互時間
timing.domInteractive – timing.fetchStart
// ready:HTML 加載完成時間,即 DOM 就位的時間
timing.domContentLoaded – timing.fetchStart
// load:頁面完全加載時間
timing.loadEventStart – timing.fetchStart
```
以上這些通過 Performance API 獲取到的時間信息都具有較高的準確度。我們可以對此進行一番格式處理之后上報給服務端,也可以基于此去制作相應的統計圖表,從而實現更加精準、更加個性化的性能耗時統計。
此外,通過訪問 performance 的 memory 屬性,我們還可以獲取到內存占用相關的數據;通過對 performance 的其它屬性方法的靈活運用,我們還可以把它耦合進業務里,實現更加多樣化的性能監測需求——靈活,是可編程化方案最大的優點。
## 小結
本節我們介紹了 Performance 開發者工具、LightHouse 與 Performance API 三種性能監測的方案。只要有 Chrome 瀏覽器,我們就可以實現上述的所有操作。
由此可以看出,性能監測本身并不難。它的復雜度是在與業務發生耦合的過程中提升的。我們今天打下了堅實的地基,后續需要大家在業務中去成長、去發掘這些工具的更多的潛力,這樣才能建立起屬于我們自己的技術金字塔。
推薦閱讀:
* [Performance 官方文檔](https://developers.google.com/web/tools/chrome-devtools/evaluate-performance/reference)
* [使用 Lighthouse 審查網絡應用](https://developers.google.com/web/tools/lighthouse/?hl=zh-cn)
* [MDN Performance API 介紹](https://developer.mozilla.org/zh-CN/docs/Web/API/Performance)
- 開篇:知識體系與小冊格局
- 網絡篇 1:webpack 性能調優與 Gzip 原理
- 網絡篇 2:圖片優化——質量與性能的博弈
- 存儲篇 1:瀏覽器緩存機制介紹與緩存策略剖析
- 存儲篇 2:本地存儲——從 Cookie 到 Web Storage、IndexDB
- 彩蛋篇:CDN 的緩存與回源機制解析
- 渲染篇 1:服務端渲染的探索與實踐
- 渲染篇 2:知己知彼——解鎖瀏覽器背后的運行機制
- 渲染篇 3:對癥下藥——DOM 優化原理與基本實踐
- 渲染篇 4:千方百計——Event Loop 與異步更新策略
- 渲染篇 5:最后一擊——回流(Reflow)與重繪(Repaint)
- 應用篇 1:優化首屏體驗——Lazy-Load 初探
- 應用篇 2:事件的節流(throttle)與防抖(debounce)
- 性能監測篇:Performance、LightHouse 與性能 API
- 前方的路:希望成為你的起點