「前端那些事兒」④ 效能監控

木_羽_發表於2019-04-01

前言

近年移動業務噴井式爆發,伴隨著網際網路人口紅利的萎縮,使用者更加青睞效率高體驗優的站點,頁面「到達」快慢直接影響了使用者的體驗,「效能」變得越來越重要。google 大資料統計觀察發現,移動端使用者對頁面載入慢的容忍度遠低於 PC 端,投放頁面首屏載入時間從 2s 鍾延遲到 3s 會造成 9.4% 的 PV 下降,8.3% 的跳出率增加以及 3.5% 的轉化率下降。效能優化具有的商業價值不言而喻,總不能眼看著市場同事辛苦「求」來的使用者在我們手中流失吧?這是身為一個合格前 yíng 臺 bīn 不能允許的!盤他!

效能優化和監控的關係

有些公司同時想到的第一件事就是「優化」,網上搜一波效能優化的列表,把別人的「最佳實踐」照搞一番,效能確實會有提升,但效率未必是最高的,反倒有些本末倒置,別人的問題未必就是自己的問題,「並行不代表因果」,要做效能優化,首先要做的是掌握詳盡的效能指標資訊,根據木桶原理,找到最拖後腿的指標「短板」,重點優化,將邊際成本最小化。所以,首先我們要做的應該是效能指標的收集分析。

三種資料收集方式

指標收集主要分有三種方式:

1、本地模擬「Lab」

以 Google 的 Lighthouse 最為著名,它是一個開源的自動化工具,可以安裝為 Chrome 的擴充套件外掛,也可以命令列直接執行,它將針對目標頁面執行一連串的測試,然後輸出一個有關頁面效能的評分報告。

根據此報告,可以有的放矢,逐一優化。

優點:

1. 評分報告全面且具有一定的權威性
2. 提供解決方案
3. 發現大的效能問題
複製程式碼

缺點:

1.存在「波動」,不同時刻的訪客群體存在差異,資料只能反應當前時刻的「效果」
2.測試環境較單一,使用者群體的環境各有不同,不可以一概之
複製程式碼

2、離線收集

將目標頁面連結「委託」給第三方的服務,執行真實的訪問指令,同時收集效能指標生成報表輸出。

這種模式是在技術變現的背景下產生的,優秀的工具都是要付費的,當然開源和免費的優秀工具也很多,此前的阿里測就是其中一種,現已下線。停運的緣由我們不好揣測,此處謹向那些開源和提供免費服務的專案致敬!此處就不再多推薦了,以免有軟文的嫌疑。

3、真實跟蹤「Field 也叫 RUM」

在目標頁面注入指令碼,在約定的時機收集效能指標資料,統一上報資料中心,資料中心集中整合生成報表,再根據報表分析效能。

優點:

1. 資料全面,可採集到所有使用者各個環境下的效能,生成直觀的分佈圖
2. 資料真實,來源於真實使用者
3. 反饋及時,優化後效果可及時地在報表上反饋出來
複製程式碼

缺點:

依賴較多,資料中心和指令碼都需要自主開發,相對成本較高
複製程式碼

所謂監控,實際上就是效能「真實跟蹤」,雖然依賴較多,但對效能指標的反饋最為真實有效。以下我們將圍繞效能監控進行展開。

效能監控

如何去評價一個頁面的效能好壞?

頁面的載入有多快?載入時間為 X.XX 秒?

其實,好與壞,快與慢,都是很模糊的概念。我們常常聽到別人介紹,「我們的頁面白屏已經從 3s 優化到了 2s」,這種陳述的問題並不是不真實,而是在於扭曲了事實。 載入白屏時間會因使用者不同而有很大的差異,具體取決於使用者的裝置效能以及網路狀況。 我們不能單純地以單個數字的形式呈現白屏時間而忽略載入時間過長的使用者。更何況,收集來的資料具有幸存者偏差性。

下圖是某頁面統計來的在一定時間段內使用者白屏時間分佈直方圖。可以直觀反應出此頁面的「效能」情況。

「前端那些事兒」④ 效能監控

我們可以說,「90% 的使用者可以在 3s 內完成頁面載入」,但「均值」或「中位數」僅能反應此頁面的某一點的表現,因為任何一個時間段都不能代表全部。

而效能優化的目標可以是增加 1s 內的使用者比重,也可以是將後面的使用者儘可能的集中在 1s-2s 之間。這些都是需要根據產品特點和目標靈活調整的。

「前端那些事兒」④ 效能監控

需要監控哪些指標

我們所需要收集且重點關注的指標,應該是能準確反應使用者體驗的指標。

體驗 表現 指標
是否發生? 導航是否成功啟動?伺服器是否有響應? 首次繪製(FP)/首次內容繪製(FCP)
是否有用? 是否已渲染可以與使用者互動的足夠內容? 首次有效繪製(FMP)/主角元素計時
是否可用? 使用者可以與頁面互動,還是頁面仍在忙於載入? 可互動時間(TTI)
是否令人愉快? 互動是否順暢而自然,沒有滯後或卡頓? 耗時較長的任務(在技術上不存在耗時較長的任務)

以下時序螢幕截圖直觀地展示了使用者體驗點對應的指標,有助大家理解。

「前端那些事兒」④ 效能監控

其中指標 FP 和 FCP 可以通過瀏覽器點 API 計算獲取,而指標 FMP 和 TTI 由於並沒有標準化的定義,因此也很難有標準化點 API 輸出, 部分原因在於很難以通用的方式界定「有效」點。

除此關鍵指標之外,我們同時也需要關注基礎指標,以便分析出造成關鍵指標「資料難看」的影響點。如 DNS 解析耗時、TCP 連線耗時、網路請求耗時以及資源載入耗時等。

標準化定義的指標

標準化定義的指標有以下幾種

PerformanceTiming

Performance.timing 是一個只讀屬性,返回 PerformanceTiming 物件,該物件包括了頁面相關的效能資訊。

「前端那些事兒」④ 效能監控

  • startTime(navigationStart):在同一個瀏覽器上下文中,前一個網頁(與當前頁面不一定同域)unload 的時間戳,如果無前一個網頁 unload ,則與 fetchStart 值相等

  • unloadEventStart:前一個網頁(與當前頁面同域)unload 的時間戳,如果無前一個網頁 unload 或者前一個網頁與當前頁面不同域,則值為 0

  • unloadEventEnd:和 unloadEventStart 相對應,返回前一個網頁 unload 事件繫結的回撥函式執行完畢的時間戳

  • redirectStart:第一個 HTTP 重定向發生時的時間。有跳轉且是同域名內的重定向才算,否則值為 0

  • redirectEnd:最後一個 HTTP 重定向完成時的時間。有跳轉且是同域名內的重定向才算,否則值為 0

  • fetchStart:瀏覽器準備好使用 HTTP 請求抓取文件的時間,這發生在檢查本地快取之前

  • domainLookupStart:DNS 域名查詢開始的時間,如果使用了本地快取(即無 DNS 查詢)或持久連線,則與 fetchStart 值相等

  • domainLookupEnd:DNS 域名查詢完成的時間,如果使用了本地快取(即無 DNS 查詢)或持久連線,則與 fetchStart 值相等

  • connectStart:HTTP(TCP) 開始建立連線的時間,如果是持久連線,則與 fetchStart 值相等,如果在傳輸層發生了錯誤且重新建立連線,則這裡顯示的是新建立的連線開始的時間

  • connectEnd:HTTP(TCP) 完成建立連線的時間(完成握手),如果是持久連線,則與 fetchStart 值相等,如果在傳輸層發生了錯誤且重新建立連線,則這裡顯示的是新建立的連線完成的時間

      注意:這裡握手結束,包括安全連線建立完成、SOCKS 授權通過
    複製程式碼
  • secureConnectionStart:HTTPS 連線開始的時間,如果不是安全連線,則值為 0

  • requestStart:HTTP 請求讀取真實文件開始的時間(完成建立連線),包括從本地讀取快取,連線錯誤重連時,這裡顯示的也是新建立連線的時間

  • responseStart:HTTP 開始接收響應的時間(獲取到第一個位元組),包括從本地讀取快取

  • responseEnd:HTTP 響應全部接收完成的時間(獲取到最後一個位元組),包括從本地讀取快取

  • domLoading:開始解析渲染 DOM 樹的時間,此時 Document.readyState 變為 loading,並將丟擲 readystatechange 相關事件

  • domInteractive:完成解析 DOM 樹的時間,Document.readyState 變為 interactive,並將丟擲 readystatechange 相關事件

      注意:只是 DOM 樹解析完成,這時候並沒有開始載入網頁內的資源
    複製程式碼
  • domContentLoadedEventStart:DOM 解析完成後,網頁內資源載入開始的時間,文件發生 DOMContentLoaded事件的時間

  • domContentLoadedEventEnd:DOM 解析完成後,網頁內資源載入完成的時間(如 JS 指令碼載入執行完畢),文件的DOMContentLoaded 事件的結束時間

  • domComplete:DOM 樹解析完成,且資源也準備就緒的時間,Document.readyState 變為 complete,並將丟擲 readystatechange 相關事件

  • loadEventStart:load 事件傳送給文件,也即 load 回撥函式開始執行的時間,如果沒有繫結 load 事件,值為 0

  • loadEventEnd:load 事件的回撥函式執行完畢的時間,如果沒有繫結 load 事件,值為 0

更多解釋參見 W3C Recommendation - NavigationTimingW3C Editor's Draft

利用以上 API,我們可以計算出細顆粒度的效能基礎指標

基礎指標 描述 計算方式 備註
rs 準備新頁面耗時 fetchStart - navigationStart
rdc 重定向時間 redirectEnd - redirectStart
dns DNS 解析耗時 domainLookupEnd - domainLookupStart
tcp TCP 連線耗時 connectEnd - connectStart
ssl SSL 安全連線耗時 connectEnd - secureConnectionStart 只在 HTTPS 下有效
ttfb Time to First Byte(TTFB),網路請求耗時 responseStart - requestStart TTFB 有多種計算方式,ARMS 以 Google Development 定義為準
trans 資料傳輸耗時 responseEnd - responseStart
dom DOM 解析耗時 domInteractive - responseEnd
res 資源載入耗時 loadEventStart - domContentLoadedEventEnd 表示頁面中的同步載入資源
fbt 首包時間 responseStart - domainLookupStart
fpt First Paint Time, 首次渲染時間 / 白屏時間 responseEnd - fetchStart 從請求開始到瀏覽器開始解析第一批 HTML 文件位元組的時間差
tti Time to Interact,首次可互動時間(非準確,僅做參考) domInteractive - fetchStart 瀏覽器完成所有 HTML 解析並且完成 DOM 構建,此時瀏覽器開始載入資源
load 頁面完全載入時間 loadEventStart - fetchStart load = 首次渲染時間 + DOM 解析耗時 + 同步 JS 執行 + 資源載入耗時

關於相容性,可參考下圖,絕大多數的瀏覽器已支援此 API,基本可以放心地使用在移動端

「前端那些事兒」④ 效能監控

Paint Timing

相對於以上基礎指標,跟使用者感受關聯最密切的可能就是各個「繪製(Paint)」時刻了,FP(First Paint),FCP(First Contentful Paint)以及 FMP(First Meaningful Paint)。

隨著 SPA(單頁面系統)的普及,單純靠 PerformanceTiming 要準確地計算出各 Paint 的時間是很難的。慶幸是的,Chrome 60+ 帶給我們一個全新的 API,Paint Timing,它提供了抓取「頁面」和「資源」耗時的能力。此 API 尚處在實驗階段,並沒有納入 W3C 的標準,所以,也僅僅是 webkit 核心的高版本瀏覽器才支援。聊勝於無。

Performance.getEntries() 方法以陣列形式對網頁中每一個物件(指令碼檔案、樣式表、圖片檔案等等)發出的請求進行統計記錄,Paint 的就是其中的一種。我們可以使用方法 performance.getEntriesByType('paint') 輕鬆獲得兩個 PerformancePaintTiming 物件,對應的分別就是 FP 和 FCP。

更多關於 FP 和 FCP,可以參考此文 www.w3cplus.com/performance…

但關於 FMP,雖然 Chrome 的 Performance 工具已指示性地標出 FMP 的時間點,但依然未提供 API,部分緣由可能就是「無法標準化」吧。

「前端那些事兒」④ 效能監控

關於 FMP

請移駕前端知識點:你知道FMP嗎?

執行的時間點

由於 Performance 的賦能,我們沒有必要在頁面「最開始」就載入執行我們的監控指令碼,再小的檔案也會阻塞首屏的繪製,但是,如果有依賴關係,如一些演算法依賴於監控 DOM 的變化,還是需要儘早進行初始化,所以時機應在 load 的前後,根據演算法的需要進行調整,並沒有一個準確的方案。

資料處理

資料收集到之後便是資料上報、處理

關於資料上報的成熟方案已有很多,「主動提交」,「反向代理」都可以,只要資料在不影響業務功能和效能的前提下完整地將上報到資料中心即可。

有了資料,我們就可以有目的性的將資料處理成我們需要的形式。

可以分析使用者分佈

image

橫向比較,細查差異因果,總結經驗。

image

也可以按時間緯度展開,嗅探時間或流量對效能的影響,也可以找到異常點,篩選出異常日誌重點關注。

image

總之,可以將有限的資料玩出無限的可能!

以上,便是對效能監控的一些基礎介紹,希望對你有所幫助。


[1] 以使用者為中心的效能指標

[2] github.com/fengzilong/…

轉載請標明出處

作者: 木羽 zwwill

首發地址:zwwill/blog#31

相關文章