如何衡量前端產(chǎn)品性能?

按指標(biāo)衡量

完...

衡量前端產(chǎn)品性能有多個(gè)指標(biāo),我們解讀一下chrome開發(fā)工具為我們提供的指標(biāo):

1. Chrome Dev Tools

Network標(biāo)簽

訪問愛奇藝首頁:

Screen Shot 2020-05-06 at 9.18.01 PM.png

421 requests - 網(wǎng)絡(luò)請(qǐng)求數(shù)
15.1 MB transferred - 數(shù)據(jù)傳輸量(壓縮)
18.2 MB resources - 數(shù)據(jù)原始大小
Finish 3.91 s - 最后請(qǐng)求完成時(shí)間
DOMContentLoaded: 758ms - DOM完全加載及解析事件觸發(fā)時(shí)間
Load: 3.83 s - 頁面加載完成觸發(fā)時(shí)間

雖然有幾百個(gè)請(qǐng)求,但頁面加載只用了4秒不到的時(shí)間,代表著非常豪華的硬件網(wǎng)絡(luò),赤裸裸地透露著有錢人的氣質(zhì)。

以上幾個(gè)指標(biāo)理解起來都不難, 我們看看在具體的某一個(gè)請(qǐng)求中有哪些信息可以參考。選中任意行并將鼠標(biāo)移到waterfall

Screen Shot 2020-05-06 at 9.23.32 PM.png

Queued at - 請(qǐng)求入隊(duì)列時(shí)間
Started at 4.67 ms - 請(qǐng)求開始時(shí)間,注意,開始并不代表請(qǐng)求發(fā)送

Resource Scheduling
Queueing 4.67 ms - 入隊(duì)耗時(shí)

Connection Start
Stalled 0.62 ms - 請(qǐng)求被掛起,會(huì)有多種原因,比如要是緩存命中的話,請(qǐng)求就不會(huì)被發(fā)送了
DNS Lookup 8.65 ms - DNS解析耗時(shí)
Initial connection 45.22 ms - 初次連接耗時(shí)
SSL 45.22 ms - SSL 耗時(shí)

Request/Response
Request sent 0.37 ms - 請(qǐng)求發(fā)送耗時(shí)
Waiting (TTFB)0.44 ms - Time to First Byte 首字節(jié)耗時(shí)
Content Download - 資源下載時(shí)間

Performance標(biāo)簽

Google 還提出了一些以用戶為中心的指標(biāo) - user centric metrics,優(yōu)秀的企業(yè)就是會(huì)搞事情。

讓我們從Network切換到Performance標(biāo)簽,再訪問愛奇藝首頁:


Screen Shot 2020-05-06 at 10.09.41 PM.png

FP - First Paint - 首次渲染,就是說開始漸進(jìn)式解析DOM結(jié)構(gòu)并在頁面上有所體現(xiàn)了
FCP - First Contentful Paint - 首次內(nèi)容渲染,此時(shí)頁面已經(jīng)包含了一些文字,圖標(biāo)等
DCL - DOMContentLoaded - DOM完全加載及解析事件觸發(fā)
FMP - First Meaningful Paint - 首次有效渲染,此時(shí)頁面已經(jīng)包含了更多文字,圖標(biāo)等
LCP - Large Content Paint - 革命就要?jiǎng)倮?br> L - Load 頁面加載完成

指標(biāo)有點(diǎn)多,就用戶體驗(yàn)而言,實(shí)際項(xiàng)目中我們多參考FP/FCP, 可以理解為白屏?xí)r間。

另外還有一個(gè)指標(biāo)叫TTI - Time to Interactive,可交互時(shí)間,它描述這樣一個(gè)時(shí)間點(diǎn)

  1. 最后一個(gè)長(zhǎng)任務(wù)完成(耗時(shí)大于等于50毫秒的任務(wù))
  2. 隨后有5秒的網(wǎng)絡(luò)和主線程空閑

這一項(xiàng)指標(biāo)要做得準(zhǔn)確比較困難,目前chrome還沒有集成。 有興趣的同學(xué)可以了解一下github GoogleChromeLabs/tti-polyfill 項(xiàng)目。

以上是chrome開發(fā)工具為我們提供的性能觀測(cè)指標(biāo),此外我們還能通過javascript 在代碼層面做一些性能監(jiān)測(cè),這需要了解一下可怕的 performance API。

2. Performance API

“It's part of the High Resolution Time API, but is enhanced by the Performance Timeline API, the Navigation Timing API, the User Timing API, and the Resource Timing API.”

這段洋文理解起來有點(diǎn)費(fèi)勁,我們先看盜圖:


performance_api_illustration.jpg

Performance API 是 High Resolution Time(高精度時(shí)間) API的子集。

Performance Timeline API 是對(duì)Performance API的擴(kuò)展,它提供了訪問其他API的統(tǒng)一入口。可以這么理解,Navigation/User/Resource/Frame/Paint Timing API 都是指標(biāo),Performance Timeline API 是訪問這些指標(biāo)的統(tǒng)一入口。

當(dāng)我們提到Performance Timeline API 可以狹義的理解為瀏覽器performance 對(duì)象中以下三個(gè)主要方法:

  • getEntries()
  • getEntriesByType()
  • getEntriesByName()

ps: 你可能知道,performance 中還有兩個(gè)對(duì)象 timing 和 navigation,通過這兩個(gè)對(duì)象可以繞開performance timeline API 直接訪問部分指標(biāo),這是早期的訪問方式,已不建議使用。

getEntries()
獲取所有項(xiàng)

getEntriesByType()
根據(jù)type獲取,可選的type有以下幾種:

  • navigation
  • resource
  • mark
  • measure
  • paint
  • longtask
  • frame
  1. navigation - Navigation Timing API
    獲取瀏覽器上下文,比如DNS查詢時(shí)間,TCP連接時(shí)間。


    Screen Shot 2020-05-07 at 9.47.06 AM.png
  2. resource - Resource Timing API
    獲取資源連接信息。


    Screen Shot 2020-05-07 at 9.50.06 AM.png
  3. mark - User Timing API
    獲取mark,配合performance.mark() 使用。

performance.mark(‘a(chǎn)lpha’)
Screen Shot 2020-05-07 at 9.56.20 AM.png
  1. measure - User Timing API
    獲取 measure,配合performance.mark(), performance.measure() 使用。
performance.mark(“alpha’)
performance.mark(“beta’)
performance.measure(“time”,”alpha”,”beta”)
Screen Shot 2020-05-07 at 10.05.42 AM.png
  1. paint - Paint Timing API
    獲取FP,F(xiàn)CP 時(shí)間。


    Screen Shot 2020-05-07 at 10.07.24 AM.png
  2. longtask - Long Tasks API

獲取耗時(shí)大于等于50毫秒的任務(wù)。

performance.getEntriesByType(‘longtask’)
  1. frame - Framing Timing API
    獲取幀變化信息,變化可由以下幾種情況觸發(fā)
  • DOM變化
  • resizing
  • scrolling
  • rendering
  • css 動(dòng)畫

此API似乎還未在chrome上實(shí)現(xiàn)。

getEntriesByName()
根據(jù)名稱獲取。

performance.getEntriesByName("first-paint")

performance.mark("alpha")
performance.getEntriesByName("alpha")

Performance.measure(‘time’,"alpha")
performance.getEntriesByName("time")

performance.getEntriesByName("https://www.a.com/logo.png")

3. 指標(biāo)監(jiān)測(cè)

通過performance timeling api 我們可以計(jì)算以下指標(biāo):

t = performance.getEntriesByType('navigation')[0]

//重定向耗時(shí)
times.redirectTime = t.redirectEnd - t.redirectStart;

//DNS查詢耗時(shí)
times.dnsTime = t.domainLookupEnd - t.domainLookupStart;

//TTFB
times.ttfbTime = t.responseStart - t.navigationStart;

//DNS緩存耗時(shí)
times.appcacheTime = t.domainLookupStart - t.fetchStart;

//卸載頁面耗時(shí)
times.unloadTime = t.unloadEventEnd - t.unloadEventStart;

//tcp連接耗時(shí)
times.tcpTime = t.connectEnd - t.connectStart;

//request請(qǐng)求耗時(shí)
times.reqTime = t.responseEnd - t.responseStart;

//解析dom樹耗時(shí)
times.analysisTime = t.domComplete - t.domInteractive;

//白屏?xí)r間 
times.blankTime = t.domInteractive - t.fetchStart;

//DOM加載耗時(shí)
times.domReadyTime = t.domContentLoadedEventEnd - t.fetchStart;

4. 響應(yīng)式監(jiān)測(cè)

通過PerformanceObserver監(jiān)測(cè)由交互、定時(shí)任務(wù)引起的變化,比如圖片懶加載。

var observer = new PerformanceObserver(list => {
      list.getEntries().forEach(entry => {
        // Display each reported measurement on console
        if (console) {
          console.log("Name: "       + entry.name      +
                      ", Type: "     + entry.entryType +
                      ", Start: "    + entry.startTime +
                      ", Duration: " + entry.duration  + "\n");
        }
      })
    });
observer.observe({entryTypes: ['resource']});

參考

10分鐘徹底搞懂前端頁面性能監(jiān)控
Performance Observer: Efficient Access to Performance Data
Breaking Down the Performance API
愛奇藝

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容