Performance

Performance

一、簡介

Web 性能是客觀的衡量標(biāo)準(zhǔn),是用戶對加載時間和運行時的直觀體驗。Web 性能指頁面加載到可交互和可響應(yīng)所消耗的時間,以及頁面在交互時的流暢度——滾動是否順滑?按鈕能否點擊?彈窗能否快速打開,動畫是否平滑?Web 性能既包括客觀的度量如加載時間,每秒幀數(shù)和到頁面可交互的時間;也包括用戶的對頁面內(nèi)容加載時間的主觀感覺。

二、關(guān)鍵性能指南

  • CSS and JavaScript animation performance

    Browsers are able to optimize rendering flows. In summary, we should always try to create our animations using CSS transitions/animations where possible. If your animations are really complex, you may have to rely on JavaScript-based animations instead.

  • dns-prefetch
    當(dāng)瀏覽器從第三方服務(wù)跨域請求資源的時候,在瀏覽器發(fā)起請求之前,這個第三方的跨域域名需要被解析為一個 IP 地址,這個過程就是 DNS 解析,DNS 緩存可以用來減少這個過程的耗時,DNS 解析可能會增加請求的延遲,對于那些需要請求許多第三方的資源的網(wǎng)站而言,DNS 解析的耗時延遲可能會大大降低網(wǎng)頁加載性能。

  • 優(yōu)化啟動性能
    不論在什么平臺上,盡可能快地啟動總是一個好主意。因為這是個很寬泛的問題,在這里我們不會著重關(guān)注。相反我們會關(guān)注構(gòu)建 Web 應(yīng)用時更重要的一個問題:盡可能異步地啟動。這意味著不要將你所有的啟動代碼在應(yīng)用主線程中的唯一一個事件處理函數(shù)中運行。

  • 關(guān)鍵渲染路徑
    關(guān)鍵渲染路徑是指瀏覽器通過把 HTML、CSS 和 JavaScript 轉(zhuǎn)化成屏幕上的像素的步驟順序。優(yōu)化關(guān)鍵渲染路徑可以提高渲染性能。關(guān)鍵渲染路徑包含了 Document Object Model (DOM),CSS Object Model (CSSOM),渲染樹和布局。

三、 使用 Performance API

Performance API

Performance 接口可以獲取到當(dāng)前頁面中與性能相關(guān)的信息。它是 High Resolution Time API 的一部分,同時也融合了 Performance Timeline API、Navigation Timing API、 User Timing API 和 Resource Timing API。該類型的對象可以通過調(diào)用只讀屬性 Window.performance 來獲得。

屬性
  • Performance.navigation

PerformanceNavigation 對象提供了在指定的時間段里發(fā)生的操作相關(guān)信息,包括頁面是加載還是刷新、發(fā)生了多少次重定向等等.

包含屬性:

type:表示是如何導(dǎo)航到這個頁面的

1:點擊刷新頁面按鈕或者通過Location.reload()方法顯示的頁面

0:當(dāng)前頁面是通過點擊鏈接,書簽和表單提交,或者腳本操作,或者在url中直接輸入地址

2:頁面通過歷史記錄和前進后退訪問時

255:任何其他方式

redirectCount:表示在到達這個頁面之前重定向了多少次

  • Performance.timing

PerformanceTiming 對象包含延遲相關(guān)的性能信息

包含屬性:

navigationStart:從同一個瀏覽器上下文的上一個文檔卸載(unload)結(jié)束時的UNIX時間戳。如果沒有上一個文檔,這個值會和PerformanceTiming.fetchStart相同;

unloadEventStart:unload事件拋出時的UNIX時間戳。如果沒有上一個文檔這個值會返回0

redirectStart:第一個HTTP重定向開始時的UNIX時間戳。如果沒有重定向,或者重定向中的一個不同源,這個值會返回0.

redirectEnd :最后一個HTTP重定向完成時(也就是說是HTTP響應(yīng)的最后一個比特直接被收到的時間)的UNIX時間戳。如果沒有重定向,或者重定向中的一個不同源,這個值會返回0;

fetchStart:瀏覽器準(zhǔn)備好使用HTTP請求來獲取(fetch)文檔的UNIX時間戳。這個時間點會在檢查任何應(yīng)用緩存之前;

domainLookupStart:表征了域名查詢開始的UNIX時間戳。如果使用了持續(xù)連接(persistent connection),或者這個信息存儲到了緩存或者本地資源上,這個值將和 PerformanceTiming.fetchStart一致;

domainLookupEnd:表征了域名查詢結(jié)束的UNIX時間戳。如果使用了持續(xù)連接(persistent connection),或者這個信息存儲到了緩存或者本地資源上,這個值將和 PerformanceTiming.fetchStart一致

connectStart:返回HTTP請求開始向服務(wù)器發(fā)送時的Unix毫秒時間戳。如果使用持久連接(persistent connection),則返回值等同于fetchStart屬性的值。

更多屬性查閱:https://developer.mozilla.org/zh-CN/docs/Web/API/PerformanceTiming

  • performance.memory

Chrome 添加的一個非標(biāo)準(zhǔn)擴展,這個屬性提供了一個可以獲取到基本內(nèi)存使用情況的對象

包含屬性:

jsHeapSizeLimit:The maximum size of the heap, in bytes, that is available to the context.

totalJSHeapSize:The total allocated heap size, in bytes.

usedJSHeapSize:The currently active segment of JS heap, in bytes.


  • Performance.timeOrigin

返回一個表示 the performance measurement 開始時間的高精度 timestamp

方法

- Performance.clearMarks()
  將給定的 mark 從瀏覽器的性能輸入緩沖區(qū)中移除。

- Performance.clearMeasures()
  將給定的 measure 從瀏覽器的性能輸入緩沖區(qū)中移除。

- Performance.clearResourceTimings()
  從瀏覽器的性能數(shù)據(jù)緩沖區(qū)中移除所有 entryType 是 "resource" 的 performance entries。

- Performance.getEntries()
  基于給定的 filter 返回一個 PerformanceEntry 對象的列表。

- Performance.getEntriesByName()
  基于給定的 name 和 entry type 返回一個 PerformanceEntry 對象的列表。

- Performance.getEntriesByType()
  基于給定的 entry type 返回一個 PerformanceEntry 對象的列表

- Performance.mark()
  根據(jù)給出 name 值,在瀏覽器的性能輸入緩沖區(qū)中創(chuàng)建一個相關(guān)的 timestamp

- Performance.measure()
  在瀏覽器的指定 start mark 和 end mark 間的性能輸入緩沖區(qū)中創(chuàng)建一個指定的 timestamp

- Performance.now()
  返回一個表示從性能測量時刻開始經(jīng)過的毫秒數(shù) DOMHighResTimeStamp

- Performance.setResourceTimingBufferSize()
  將瀏覽器的資源 timing 緩沖區(qū)的大小設(shè)置為 "resource" type performance entry 對象的指定數(shù)量
- Performance.toJSON()
  其是一個 JSON 格式轉(zhuǎn)化器,返回 Performance 對象的 JSON 對象


使用例子
  • 計算資源加載各階段的時間

重定向 (redirectStart 和 redirectEnd ),DNS 查詢(domainLookupStart 和 domainLookupEnd),TCP 握手 (connectStart 和 connectEnd), 響應(yīng) (responseStart 和 responseEnd)。 這段例子也計算了從開始獲取資源和請求開始(分別為 fetchStart and requestStart)到響應(yīng)結(jié)束 (responseEnd) 的時間

function calculate_load_times() {
  // Check performance support
  if (performance === undefined) {
    console.log("= Calculate Load Times: performance NOT supported");
    return;
  }

  // Get a list of "resource" performance entries
  var resources = performance.getEntriesByType("resource");
  if (resources === undefined || resources.length <= 0) {
    console.log("= Calculate Load Times: there are NO `resource` performance records");
    return;
  }

  console.log("= Calculate Load Times");
  for (var i=0; i < resources.length; i++) {
    console.log("== Resource[" + i + "] - " + resources[i].name);
    // Redirect time
    var t = resources[i].redirectEnd - resources[i].redirectStart;
    console.log("... Redirect time = " + t);

    // DNS time
    t = resources[i].domainLookupEnd - resources[i].domainLookupStart;
    console.log("... DNS lookup time = " + t);

    // TCP handshake time
    t = resources[i].connectEnd - resources[i].connectStart;
    console.log("... TCP time = " + t);

    // Secure connection time
    t = (resources[i].secureConnectionStart > 0) ? (resources[i].connectEnd - resources[i].secureConnectionStart) : "0";
    console.log("... Secure connection time = " + t);

    // Response time
    t = resources[i].responseEnd - resources[i].responseStart;
    console.log("... Response time = " + t);

    // Fetch until response end
    t = (resources[i].fetchStart > 0) ? (resources[i].responseEnd - resources[i].fetchStart) : "0";
    console.log("... Fetch until response end time = " + t);

    // Request start until reponse end
    t = (resources[i].requestStart > 0) ? (resources[i].responseEnd - resources[i].requestStart) : "0";
    console.log("... Request start until response end time = " + t);

    // Start until reponse end
    t = (resources[i].startTime > 0) ? (resources[i].responseEnd - resources[i].startTime) : "0";
    console.log("... Start until response end time = " + t);
  }
}

  • 計算資源大小
function display_size_data(){
  // Check for support of the PerformanceResourceTiming.*size properties and print their values
  // if supported.
  if (performance === undefined) {
    console.log("= Display Size Data: performance NOT supported");
    return;
  }

  var list = performance.getEntriesByType("resource");
  if (list === undefined) {
    console.log("= Display Size Data: performance.getEntriesByType() is  NOT supported");
    return;
  }

  // For each "resource", display its *Size property values
  console.log("= Display Size Data");
  for (var i=0; i < list.length; i++) {
    console.log("== Resource[" + i + "] - " + list[i].name);
    if ("decodedBodySize" in list[i])
      console.log("... decodedBodySize[" + i + "] = " + list[i].decodedBodySize);
    else
      console.log("... decodedBodySize[" + i + "] = NOT supported");

    if ("encodedBodySize" in list[i])
      console.log("... encodedBodySize[" + i + "] = " + list[i].encodedBodySize);
    else
      console.log("... encodedBodySize[" + i + "] = NOT supported");

    if ("transferSize" in list[i])
      console.log("... transferSize[" + i + "] = " + list[i].transferSize);
    else
      console.log("... transferSize[" + i + "] = NOT supported");
  }
}
  • 測量執(zhí)行性能
// 標(biāo)記一個開始點
performance.mark("mySetTimeout-start");

// 等待1000ms
setTimeout(function() {
  // 標(biāo)記一個結(jié)束點
  performance.mark("mySetTimeout-end");

  // 標(biāo)記開始點和結(jié)束點之間的時間戳
  performance.measure(
    "mySetTimeout",
    "mySetTimeout-start",
    "mySetTimeout-end"
  );

  // 獲取所有名稱為mySetTimeout的measures
  var measures = performance.getEntriesByName("mySetTimeout");
  var measure = measures[0];
  console.log("setTimeout milliseconds:", measure.duration)

  // 清除標(biāo)記
  performance.clearMarks();
  performance.clearMeasures();
}, 1000);
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • ? 性能監(jiān)控 在前端一直是一個口頭上備受關(guān)注但開發(fā)中又常被忽略的點,畢竟不是每個開發(fā)者很容易就做到的事。好在HTM...
    果汁涼茶丶閱讀 5,558評論 0 8
  • 今天要做一個監(jiān)控頁面性能的插件,并把性能數(shù)據(jù)上報到數(shù)據(jù)庫,由此接觸到了performance。 一.什么是perf...
    我的木閱讀 2,067評論 0 1
  • 原文 :web計時機制——performance對象 前面的話 頁面性能一直都是Web開發(fā)人員比較關(guān)注的領(lǐng)域。但在...
    R_X閱讀 700評論 0 1
  • 簡介 performance是html5的新特性之一,通過它,我們前端開發(fā)者們就可以非常精確的統(tǒng)計到自己頁面的性能...
    elle0903閱讀 2,870評論 0 2
  • 夜鶯2517閱讀 128,185評論 1 9

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