作为前端开发,肯定对 Chrome 的 dev tools 不陌生,除了日常 Debug,还提供了一个非常强大的功能:performance 用做性能分析。

window.performance 提供了一组精确的数据,配合数据上报即可实现简单的性能统计。

1. 属性字段
首先可以打开官方提供的测试页:https://googlechrome.github.io/devtools-samples/jank/,在 Chrome 控制台下输入 window.performance 即可得到 performance 属性字段。

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. 常用性能数据指标计算

封装常用性能指标统计函数

// 计算加载时间
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:已使用的内存

  4. 参考:

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

posted on 2021-08-04 17:39  刘世涛6192  阅读(499)  评论(0编辑  收藏  举报