天天看點

Chrome Dev Tools 之 PerformanceChrome Dev Tools 之 Performance

Chrome Dev Tools 之 Performance

作為前端開發,肯定對 Chrome 的 dev tools 不陌生,除了日常 Debug,還提供了一個非常強大的功能:performance 用做性能分析。

window.performance 提供了一組精确的資料,配合資料上報即可實作簡單的性能統計。

1. 屬性字段

首先可以打開官方提供的測試頁:<https://googlechrome.github.io/devtools-samples/jank/>,在 Chrome 控制台下輸入

window.performance

即可得到 performance 屬性字段。

Chrome Dev Tools 之 PerformanceChrome Dev Tools 之 Performance

01.png

var performance = {
    // memory 記憶體 ( only Chrome )
    memory: {
        usedJSHeapSize:  17045133, // JS對象占用的記憶體
        totalJSHeapSize: 18463485, // 可使用的總記憶體
        jsHeapSizeLimit: 2197815296 // 記憶體大小限制
    },
    // navigation 導航
    navigation: {
        redirectCount: 0, // 重定向次數
        type: 0           // 0 TYPE_NAVIGATENEXT 正常進入的頁面(非重新整理、非重定向等)
                          // 1 TYPE_RELOAD 通過 window.location.reload() 重新整理的頁面
                          // 2 TYPE_BACK_FORWARD 通過浏覽器的前進後退按鈕進入的頁面
                          // 255 TYPE_UNDEFINED 非以上方式進入的頁面
    },
 	// timing 時間
    timing: {
        // 前一個網頁 unload 的時間戳
        navigationStart: 1573989694438,
        // 前一個網頁(與目前頁面同域) unload 開始的時間戳
        unloadEventStart: 0,
        // 前一個網頁(與目前頁面同域) unload 結束的時間戳
        unloadEventEnd: 0,
        // 第一個 HTTP 重定向發生時的時間。有跳轉且是同域名内的重定向才算,否則值為 0
        redirectStart: 0,
        // 最後一個 HTTP 重定向完成時的時間。有跳轉且是同域名内部的重定向才算,否則值為 0
        redirectEnd: 0,
        // 浏覽器準備好使用 HTTP 請求抓取文檔的時間
        fetchStart: 1573989694445,
        // DNS 域名查詢開始的時間
        domainLookupStart: 1573989694445,
        // DNS 域名查詢完成的時間
        domainLookupEnd: 1573989694445,
        // HTTP 開始建立連接配接的時間
        connectStart: 1573989694445,
        // HTTP 完成建立連接配接的時間
        connectEnd: 1573989694445,
        // HTTPS 連接配接開始的時間
        secureConnectionStart: 0,
        // HTTP 請求完成建立連接配接
        requestStart: 1573989694564,
        // HTTP 開始接收響應的時間
        responseStart: 1573989694605,
        // HTTP 響應全部接收完成的時間
        responseEnd: 1573989694618,
        // DOM 樹開始解析渲染
        domLoading: 1573989694688,
        // DOM 解析完成,資源未加載的時間
        domInteractive: 1573989696189,
        // DOM 解析完成,資源加載開始的時間
        domContentLoadedEventStart: 1573989696189,
        // DOM 解析完成,網頁内資源加載完成的時間
        domContentLoadedEventEnd: 1573989696330,
        // DOM 解析完成,且資源準備就緒的時間
        domComplete: 1573989697523,
        // load 事件回調函數開始執行的時間 (若未綁定 load 事件,值為 0)
        loadEventStart: 1573989697531,
        // load 事件回調函數執行完畢的時間
        loadEventEnd: 1573989697553
    }
};           

複制

2. 常用性能資料名額計算

Chrome Dev Tools 之 PerformanceChrome Dev Tools 之 Performance

02.png

封裝常用性能名額統計函數

// 計算加載時間
function getPerformanceTiming () {  
    var performance = window.performance;
    if (!performance) {
        console.log('你的浏覽器不支援 performance 接口');
        return;
    }
    var t = performance.timing;
    var times = {};
    
    // * 使用者等待整個頁面加載完成的時間
    times.loadPage = t.loadEventEnd - t.navigationStart;
    // * DOM 樹解析時間
    times.domReady = t.domComplete - t.responseEnd;
    // * 重定向的時間
    times.redirect = t.redirectEnd - t.redirectStart;
    // * DNS 解析時間
    times.lookupDomain = t.domainLookupEnd - t.domainLookupStart;
    // * 白屏時間 TTFB (Time To First Byte)  ? cdn
    times.ttfb = t.responseStart - t.navigationStart;
    // * 内容加載完成的時間  ? gzip 檔案壓縮
    times.request = t.responseEnd - t.requestStart;
    // 執行 onload 回調函數的時間  ? onload回調函數執行過多,延遲加載、懶加載
    times.loadEvent = t.loadEventEnd - t.loadEventStart;
    // DNS 緩存時間 (App Cache)
    times.appcache = t.domainLookupStart - t.fetchStart;
    // 解除安裝頁面的時間
    times.unloadEvent = t.unloadEventEnd - t.unloadEventStart;
    // TCP 連接配接時間
    times.connect = t.connectEnd - t.connectStart;
 
    return times;
}           

複制

3. 其他 api

3.1 performance.getEntries()

傳回值為所有資源的加載情況的數組,除了

performance.timing

中包含的部分屬性,新增四個屬性:

name: "http://cdn.xxx/xxx.css",  // 資源名稱(絕對路徑)
entryType: "resource",           // 資源類型
initiatorType: "link",           // link => <link>标簽
                                 // script => <script>标簽
                                 // redirect => 重定向
duration: 18.00099999999999      // 加載時間           

複制

封裝擷取對某個資源的加載情況:

function getEntryTiming (entry) {
    var t = entry;
    var times = {};
    // 重定向時間
    times.redirect = t.redirectEnd - t.redirectStart;
    // DNS查詢時間
    times.lookupDomain = t.domainLookupEnd - t.domainLookupStart;
    // 内容加載完成的時間
    times.request = t.responseEnd - t.requestStart;
    // TCP 建立連接配接完成握手的時間
    times.connect = t.connectEnd - t.connectStart;
	// 新增屬性
    times.name = entry.name;
    times.entryType = entry.entryType;
    times.initiatorType = entry.initiatorType;
    times.duration = entry.duration;
    return times;
}           

複制

3.2 performance.now() / performance.mark()

精确計算程式執行時間,

performance.now()

傳回以微秒為機關的時間,更加精準,而且

Date.now()

可能受系統時間影響且可能阻塞,而

performance.now()

輸出的是相對于

performance.timing.navigationStart

(頁面初始化) 的時間,而

performance.mark()

則可以在程式中進行時間打點存儲,以便後面分析。

performance.now()

function getFunctionTimeWithPerformance (func) {  
    var timeStart = window.performance.now();
    func();
    var timeEnd = window.performance.now();
    return (timeEnd - timeStart);
}           

複制

performance.mark()

function randomFunc (n) {
    if (!n) {
        n = ~~(Math.random() * 10000); // 生成一個随機數
    }
    var nameStart = 'markStart' + n;
    var nameEnd   = 'markEnd' + n;
    var name = 'measureRandomFunc' + n;
    // 函數執行前做标記
    window.performance.mark(nameStart);
    for (var i = 0; i < n; i++) {
        // do nothing
    }
    // 函數執行後再做标記
    window.performance.mark(nameEnd);
    // 測量這個兩個标記的時間距離,并儲存
    window.performance.measure(name, nameStart, nameEnd);
}
randomFunc();  
randomFunc(888);
// 檢視儲存的标記
var marks = window.performance.getEntriesByType('mark');
var measure = window.performance.getEntriesByType('measure');
var entries = window.performance.getEntriesByName('measureRandomFunc888'); // 檢視自定義測量
console.log(marks,measure,entries);
// 清除标記
window.performance.clearMarks('markStart888'); // 清除指定标記
window.performance.clearMarks(); // 清除所有标記
window.performance.clearMeasures('measureRandomFunc');
window.performance.clearMeasures();           

複制

使用

measure

計算 domReady 時間

// 舊方案
var t = performance.timing  
var domReadyTime = t.domComplete - t.responseEnd;
console.log(domReadyTime)
// 新方案
window.performance.measure('domReady','responseEnd','domComplete');
var domReadyMeasure = window.performance.getEntriesByName('domReady');
console.log(domReadyMeasure);           

複制

3.3 performance.memory

檢視浏覽器記憶體情況,包含:

  1. jsHeapSizeLomit

    :記憶體大小限制
  2. totalJSHeadSize

    :可使用的記憶體
  3. userdJSHeadSize

    :已使用的記憶體

參考:

https://developers.google.cn/web/tools/chrome-devtools/network/understanding-resource-timing