<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          前端不哭!webview 性能優(yōu)化,應(yīng)該關(guān)注哪些指標(biāo)?(好文收藏)

          共 6433字,需瀏覽 13分鐘

           ·

          2021-11-11 19:35


          前一段時(shí)間,ELab團(tuán)隊(duì)對(duì) webview 做了一期性能優(yōu)化,在優(yōu)化過(guò)程中,我們追求的是頁(yè)面要足夠「快」「穩(wěn)」。那怎么定量地衡量這個(gè)「快」「穩(wěn)」呢?性能指標(biāo)幫助我們從數(shù)據(jù)化角度了解頁(yè)面性能現(xiàn)狀,性能瓶頸以及優(yōu)化完成后,衡量?jī)?yōu)化效果。

          性能指標(biāo)在日常開(kāi)發(fā)中,大家或多或少的都有接觸。比如?? 是一個(gè)頁(yè)面在 Lighthouse 下跑出來(lái)的性能數(shù)據(jù)。

          這篇文章將回答下面幾個(gè)問(wèn)題:

          • 哪些性能指標(biāo)是需要觀測(cè)的?它們是什么含義?
          • 這么多指標(biāo),我們?cè)谑裁磮?chǎng)景下應(yīng)該關(guān)注哪些?
          • 指標(biāo)是怎么采集的?

          常用的性能指標(biāo)

          • First Paint
          • First Contentful Paint
          • Largest Contentful Paint
          • First Meaningful Paint
          • First Input Delay
          • Cumulative Layout Shift
          • Time to Interactive
          • DOMContentLoaded
          • Load

          First Paint(FP) 首次繪制

          首次渲染的時(shí)間點(diǎn),可以視為白屏?xí)r間,比如完成背景色渲染的時(shí)間點(diǎn)。通常作為時(shí)間點(diǎn)最早的一個(gè)性能指標(biāo)。

          First Contentful Paint(FCP) 首次內(nèi)容繪制

          首次有內(nèi)容渲染的時(shí)間點(diǎn),指標(biāo)測(cè)量頁(yè)面從開(kāi)始加載到頁(yè)面內(nèi)容的任何部分在屏幕上完成渲染的時(shí)間。對(duì)于該指標(biāo),"內(nèi)容"指的是文本、圖像、元素或非白色的元素。可以作為首屏?xí)r間。

          FP vs FCP

          FP:從開(kāi)始加載到第一次渲染

          FCP:從開(kāi)始加載到第一次內(nèi)容渲染。

          FCP 是 FP 的增強(qiáng)版,對(duì)用戶來(lái)說(shuō)更關(guān)鍵。因?yàn)?FCP 帶著圖像和文字這些內(nèi)容信息,是用戶更關(guān)心的。

          FP 和 FCP 可能是重合的。

          Largest Contentful Paint (LCP) 最大內(nèi)容繪制

          頁(yè)面的最大內(nèi)容(通常是比較核心的內(nèi)容)加載完成的時(shí)間,這個(gè)最大內(nèi)容可以是圖片/文本塊。它是一個(gè) SEO 相關(guān)的指標(biāo)。

          LCP vs FCP

          FCP:頁(yè)面加載過(guò)程中,比較早期的一個(gè)指標(biāo),如果一個(gè)頁(yè)面有 loading 態(tài),這個(gè)指標(biāo)表現(xiàn)可能很好,但是實(shí)際內(nèi)容什么時(shí)候呈現(xiàn)給用戶,這個(gè)指標(biāo)沒(méi)辦法衡量。

          LCP:關(guān)注頁(yè)面核心內(nèi)容呈現(xiàn)時(shí)間,這個(gè)內(nèi)容是用戶更感興趣的,更加用戶相關(guān)。

          First Meaningful Paint(FMP) 首次有效繪制

          首次繪制有意義內(nèi)容的時(shí)間。業(yè)界比較認(rèn)可的方式是在加載和渲染過(guò)程中最大布局變動(dòng)之后的那個(gè)繪制時(shí)間即為當(dāng)前頁(yè)面的 FMP。因?yàn)樗?jì)算相對(duì)復(fù)雜,且存在準(zhǔn)確性等問(wèn)題,Lighthouse 6.0 中被廢棄。

          LCP vs FMP

          FMP: 早期比較推薦的性能指標(biāo),但是計(jì)算更復(fù)雜,而且準(zhǔn)確性不是很好

          LCP: 更新的數(shù)據(jù)指標(biāo),有 API 直接支持,統(tǒng)計(jì)簡(jiǎn)單,且準(zhǔn)確,但也存在最大內(nèi)容是否為最核心內(nèi)容這樣的問(wèn)題。

          First Input Delay(FID) 首次輸入延遲

          這個(gè)指標(biāo)的觸發(fā)是在用戶第一次與頁(yè)面交互的的時(shí)候,記錄的是是用戶第一次與頁(yè)面交互到瀏覽器真正能夠開(kāi)始處理事件處理程序以響應(yīng)該交互的時(shí)間,即交互延遲時(shí)間。比如發(fā)生在用戶第一次在頁(yè)面進(jìn)行 click, keydown 等交互。

          為什么會(huì)有這樣的延遲呢?一般來(lái)說(shuō),發(fā)生輸入延遲是因?yàn)闉g覽器的主線程正忙著執(zhí)行其他工作(比如解析和執(zhí)行大型 JS 文件),還不能響應(yīng)用戶。

          Cumulative Layout Shift(CLS) 累積布局偏移

          在一個(gè)頁(yè)面的生命周期中,會(huì)不斷的發(fā)生布局變化(layout shift),對(duì)每一次布局變化做一個(gè)累積的記分,其中得分最大布局變化即為 CLS。是衡量頁(yè)面穩(wěn)定性的重要指標(biāo)(visual stability)

          糟糕的 CLS 對(duì)用戶體驗(yàn)的影響??

          Core Web Vitals

          2020 年 5 月,Google 提出的衡量網(wǎng)站用戶體驗(yàn)的核心數(shù)據(jù)指標(biāo),涵蓋了頁(yè)面的加載速度、可交互性和穩(wěn)定性。是近期生效的會(huì)影響 SEO 的重要指標(biāo),包含一下三項(xiàng):

          • LCP
          • FID
          • CLS

          Time to Interactive(TTI) 可交互時(shí)間

          說(shuō)到 TTI 首先要介紹下 Long Task

          Long Task:如果瀏覽器主線程執(zhí)行的一個(gè) task 耗時(shí)大于 50ms,那么這個(gè) task 稱為 long task。用戶的交互操作也是在主線程執(zhí)行的,所以當(dāng)發(fā)生 Long Task 時(shí),用戶的交互操作很可能無(wú)法及時(shí)執(zhí)行,這時(shí)用戶就會(huì)體驗(yàn)到卡頓(當(dāng)頁(yè)面響應(yīng)時(shí)間超過(guò) 100ms 時(shí),用戶可以體驗(yàn)到卡頓),進(jìn)而影響用戶體驗(yàn)。

          從頁(yè)面加載開(kāi)始到頁(yè)面處于完全可交互狀態(tài)所花費(fèi)的時(shí)間。通常是發(fā)生在頁(yè)面依賴的資源已經(jīng)加載完成,此時(shí)瀏覽器可以快速響應(yīng)用戶交互的時(shí)間。

          DOMContentLoaded(DCL)

          DOM 加載完成即觸發(fā),不用等頁(yè)面資源加載。

          Load(L)

          頁(yè)面及其依賴的資源全部加載完成的時(shí)間,包括所有的資源文件,如樣式表和圖片等。

          常見(jiàn)的性能名詞

          以用戶為中心的性能指標(biāo) (user-centric metric)

          傳統(tǒng)性能指標(biāo):

          很長(zhǎng)時(shí)間以來(lái),描述性能是通過(guò) Load/DOMContentLoaded 事件進(jìn)行測(cè)量的,一個(gè)網(wǎng)站加載完成的時(shí)間是多少秒。雖然 Load/DOMContentLoaded 是頁(yè)面生命周期中比較明確的時(shí)刻,但是它真的能很好的反應(yīng)實(shí)際用戶訪問(wèn)頁(yè)面的真實(shí)感受嗎?

          比如,服務(wù)器如果響應(yīng)一個(gè)很小的體積的頁(yè)面,Load/DOMContentLoaded 會(huì)很快觸發(fā),然后異步獲取內(nèi)容,之后在頁(yè)面上顯示。這樣的頁(yè)面 Load/DOMContentLoaded 的時(shí)間很短,那從用戶體驗(yàn)角度講它的性能表現(xiàn)就是好的嗎?

          要回答上面問(wèn)題,也就引出了?? 這個(gè)概念。

          以用戶為中心的性能指標(biāo) (user-centric metric):

          以用戶為中心的性能指標(biāo)更關(guān)注從用戶角度看,頁(yè)面的性能是怎樣的?頁(yè)面呈現(xiàn)的內(nèi)容是不是滿足用戶需要,用戶交互起來(lái)是否流暢等。上面介紹的 FCP、LCP、FMP、FID、CLS、TTI 均是以用戶為中心的性能指標(biāo)

          是否正在發(fā)生?導(dǎo)航是否成功啟動(dòng)?服務(wù)器有響應(yīng)嗎?
          是否有用?是否渲染了足夠的內(nèi)容讓用戶可以深入其中?
          是否可用?頁(yè)面是否繁忙,用戶是否可以與頁(yè)面進(jìn)行交互?
          是否令人愉快?交互是否流暢自然,沒(méi)有延遲和卡頓?

          根據(jù)采集方式不同,性能指標(biāo)的幾種形式

          根據(jù)測(cè)量方式的不同,性能數(shù)據(jù)可以分為:Lab Data 和 Field Data

          Lab Data / SYN

          SYN 即 synthetic monitoring,收集形式也有叫 in the lab

          Lab Data 是在可控的條件下,特定的機(jī)型,特定的網(wǎng)絡(luò)環(huán)境,收集的性能數(shù)據(jù)。一個(gè)使用場(chǎng)景是,新頁(yè)面開(kāi)發(fā)的時(shí)候,頁(yè)面發(fā)布到生產(chǎn)環(huán)境中之前,是沒(méi)辦法基于真實(shí)用戶做性能指標(biāo)測(cè)量的,此時(shí),想了解也沒(méi)性能情況,可以通過(guò) Lab 方式收集和檢查。

          Field Data / RUM

          RUM 即 Real User Monitoring,收集形式也有叫 in the Filed

          Lab 的方式測(cè)量雖然能反應(yīng)性能情況,但是真實(shí)用戶因機(jī)型和網(wǎng)絡(luò)情況各異,頁(yè)面加載對(duì)于不同用戶具有很大的不確定性,Lab 數(shù)據(jù)并不一定是真實(shí)用戶的實(shí)際情況。而 filed 數(shù)據(jù)很好的解決了這個(gè)問(wèn)題,有一定的代碼侵入性,記錄真實(shí)用戶的性能數(shù)據(jù),通過(guò) RUM 數(shù)據(jù)可以發(fā)現(xiàn)一些 Lab 數(shù)據(jù)下很難暴露出來(lái)的性能異常。

          RAIL Model

          我們先來(lái)看下 RAIL 這幾個(gè)字母分別對(duì)應(yīng)什么?

          R: response

          A: animation

          I: idle

          L: load

          RAIL 是 Google 提出的以用戶為中心的一套性能模型,從各個(gè)維度反應(yīng)一個(gè)網(wǎng)站的性能情況,同時(shí)提供一組性能目標(biāo)供參考??

          • Response: 50ms 內(nèi)對(duì)事件做出響應(yīng)
          • Animation: 動(dòng)畫 10 ms 內(nèi)生成內(nèi)一幀(每幀耗時(shí) 16ms,用戶會(huì)感到動(dòng)畫流暢,為什么這里是 10ms?)
          • Idle: 最大化的利用上空閑時(shí)間
          • Load: 在 5s 內(nèi)完成內(nèi)容傳輸并達(dá)到用戶可交互

          性能指標(biāo)是怎么采集的

          性能指標(biāo)相關(guān)的 API 及采集方式

          Performance Observer[1]

          Performance Observer API 下包含一組性能監(jiān)測(cè)相關(guān)的 API

          • Paint Timing API
          • Largest Contentful Paint API
          • Event Timing API
          • Navigation Timing API
          • Layout Instability API
          • Long Tasks API
          • Resource Timing API

          下面按照不同指標(biāo)的收集用到的 API 依次介紹它們是怎么用的。

          Paint Timing API[2]

          用于收集 FP / FCP

          new?PerformanceObserver((list)?=>?{

          ??for?(const?entry?of?list.getEntries())?{

          ????console.log('FCP:?',?entry.startTime);

          ??}

          }).observe({

          ??type:?'first-contentful-paint',

          ??buffered:?true,

          });



          new?PerformanceObserver((list)?=>?{

          ??for?(const?entry?of?list.getEntries())?{

          ????console.log('FP:?',?entry.startTime);

          ??}

          }).observe({

          ??type:?'first-paint',

          ??buffered:?true,

          });

          Largest Contentful Paint API[3]

          用于收集 LCP

          largest-contentful-paint 事件會(huì)在頁(yè)面加載過(guò)程中根據(jù)此時(shí)已渲染最大元素的變化,不斷的被觸發(fā),實(shí)際上報(bào)中會(huì)一直監(jiān)聽(tīng)這些變化,直到用戶與頁(yè)面發(fā)生交互行為(比如 click、keydown)或者頁(yè)面被隱藏或者頁(yè)面被 unload 等,取監(jiān)聽(tīng)到的最后值做上報(bào)。

          new?PerformanceObserver(entryList?=>?{

          ??for?(const?entry?of?entryList.getEntries())?{

          ????console.log('LCP:?',?entry.startTime);

          ??}

          }).observe({

          ????type:?'largest-contentful-paint',

          ????buffered:?true

          });


          完整版代碼參考???

          https://github.com/GoogleChrome/web-vitals/blob/main/src/getLCP.ts

          這個(gè)指標(biāo)是 Core Web Vitals,但是兼容性不好,iOS 下都是不支持的??

          Event Timing API[4]

          用于收集 FID

          監(jiān)聽(tīng)用戶的第一次輸入(first-input)事件,F(xiàn)ID = 開(kāi)始處理 input 的時(shí)間 - input 操作的起始時(shí)間

          new?PerformanceObserver(list?=>?{

          ??for?(const?entry?of?list.getEntries())?{

          ????//?開(kāi)始處理?input?的時(shí)間?-?input?操作的起始時(shí)間

          ????const?FID?=?entry.processingStart?-?entry.startTime;?

          ????console.log('FID:',?FID);

          ??}

          }).observe({

          ??type:?'first-input',

          ??buffered:?true,

          });

          Navigation Timing 1.0[5]Navigation Timing 2.0[6]

          用于收集 Load / DOMContentLoaded

          new?PerformanceObserver(list?=>?{

          ??for?(const?entry?of?list.getEntries())?{

          ????const?Load?=?entry.loadEventStart?-?entry.fetchStart;

          ????console.log('Load:',?Load);

          ??}

          }).observe({

          ??type:?'navigation',

          ??buffered:?true,

          });



          new?PerformanceObserver(list?=>?{

          ??for?(const?entry?of?list.getEntries())?{

          ????const?DOMContentLoaded?=?entry.domContentLoadedEventStart?-?entry.fetchStart;

          ????console.log('DOMContentLoaded:',?DOMContentLoaded);

          ??}

          }).observe({

          ??type:?'navigation',

          ??buffered:?true,

          });

          Layout Instability API[7]

          收集 CLS: 將加載過(guò)程分塊(session),監(jiān)聽(tīng) layout-shift 變化獲得每次布局變動(dòng)的 value 值,統(tǒng)計(jì)每個(gè) session 的布局變動(dòng)分?jǐn)?shù),最大的布局變動(dòng)分?jǐn)?shù)時(shí)段,即為 CLS。

          let?sessionEntries?=?[];

          let?sessionValue?=?0;

          let?metric?=?{

          ??value:?0

          }

          new?PerformanceObserver(entryList?=>?{

          ??for?(const?entry?of?entryList.getEntries())?{

          ????if?(!entry.hadRecentInput)?{

          ??????const?firstSessionEntry?=?sessionEntries[0];

          ??????const?lastSessionEntry?=?sessionEntries[sessionEntries.length?-?1];



          ??????//?如果時(shí)間靠近上一個(gè)?session,?將本輪?layout-shift?累加進(jìn)上一個(gè)?session

          ??????if?(sessionValue?&&

          ??????????entry.startTime?-?lastSessionEntry.startTime?
          ??????????entry.startTime?-?firstSessionEntry.startTime?
          ????????sessionValue?+=?entry.value;

          ????????sessionEntries.push(entry);

          ??????}?else?{?//?新起一個(gè)?session

          ????????sessionValue?=?entry.value;

          ????????sessionEntries?=?[entry];

          ??????}



          ??????//?如果當(dāng)前?session?的?value?大于之前的最大值,替換為現(xiàn)在這個(gè)大的

          ??????if?(sessionValue?>?metric.value)?{

          ????????metric.value?=?sessionValue;

          ????????metric.entries?=?sessionEntries;

          ????????console.log('CLS:?',?metric)

          ??????}

          ????}

          ??}

          }).observe({

          ????type:?'layout-shift',

          ????buffered:?true

          });

          完整代碼見(jiàn)???
          https://github.com/GoogleChrome/web-vitals/blob/main/src/getCLS.ts

          Long Tasks API[8] & Resource Timing API[9]

          TTI 的采集依賴這兩個(gè) API,計(jì)算過(guò)程:

          1. 先采集 FCP,作為起點(diǎn)
          2. 沿時(shí)間軸正向搜索時(shí)長(zhǎng)至少為 5 秒的安靜窗口(安靜窗口:沒(méi)有 Long Task 且不超過(guò)兩個(gè)正在處理的網(wǎng)絡(luò) GET 請(qǐng)求)
          3. 沿時(shí)間軸反向搜索安靜窗口之前的最后一個(gè)長(zhǎng)任務(wù),如果沒(méi)有找到長(zhǎng)任務(wù),則在 FCP 步驟停止執(zhí)行
          4. TTI 是安靜窗口之前最后一個(gè)長(zhǎng)任務(wù)的結(jié)束時(shí)間,如果沒(méi)有找到長(zhǎng)任務(wù),則與 FCP 值相同

          —— Time to Interactive (TTI)[10]

          Mutation[11] [12]Observer[13]

          收集 FMP:通過(guò) MutationObserver 對(duì) DOM 變化進(jìn)行監(jiān)聽(tīng),每次回調(diào)根據(jù)新舊 DOM 數(shù)量、種類、深度等,計(jì)算出當(dāng)前 DOM 樹的分?jǐn)?shù),分?jǐn)?shù)變化最劇烈的時(shí)刻視為 FMP ,Load 事件觸發(fā)后 200ms 停止監(jiān)聽(tīng),取最大變動(dòng)的記錄做上報(bào)。

          new?MutationObserver(()?=>?{

          ??//?這里是劇烈程度分的計(jì)算

          }).observe(document,?{

          ??childList:?true,

          ??subtree:?true,

          });

          業(yè)界性能指標(biāo)采集工具

          In the Lab

          • Chrome DevTools[14]
          • Lighthouse[15]
          • WebPageTest[16]

          In the Field

          • web-vitals[17]

          參考

          Web Vitals[18]

          Largest Contentful Paint (LCP)[19]

          Cumulative Layout Shift (CLS)[20]

          First Input Delay (FID)[21]

          Measure performance with the RAIL model[22]


          ?CocosStore 雙11來(lái)臨!限時(shí)5折優(yōu)惠開(kāi)啟
          參與活動(dòng)領(lǐng)取Cocos定制周邊

          明天 11.11 Cocos微店將全面開(kāi)啟限時(shí)5折優(yōu)惠
          CocosStore 部分作品參與活動(dòng)
          游戲開(kāi)發(fā),技術(shù)變現(xiàn),期待你的參與!

          瀏覽 128
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日韩国产精品毛片 | 欧美黑人大群交舔舔舔 | 欧美操妣免费看 | 欧美操逼视频在线免费观看 | 国产精彩视频免费观看 |