前端利用Performance进行性能监控

140 阅读4分钟

前言

在日常的项目开发过程中,开发需要知道项目在客户端运行的性能,包括页面白屏耗时, 完全加载耗时, 解析dom树耗时等等一系列的性能指标,然后根据这些性能指标对项目进行相应的优化。所以可以通过浏览器开发者工具下的performance进行性能监控,performance API是浏览器暴露给js的接口,可以通过这个接口来获取我们所需的性能指标,在浏览器开发者工具输入performance会得到如下图所示:

image.png

1、performance.timing的属性介绍

下图是页面加载流程:

image.png 接下来看一下Performanc.timing这个API的对象属性,如下:

标题描述
connectStart浏览器向服务器请求文档,开始建立连接的时间,如果此连接是一个长连接,或者无需与服务器连接(命中缓存),则返回domainLookupEnd的值
connectEnd浏览器向服务器请求文档,建立连接成功的时间
domComplete浏览器把document.readyState设置为“complete”的时间点
domContentLoadedEventStart文档发生DOMContentLoaded事件的时间
domContentLoadedEventEnd文档的DOMContentLoaded事件结束的时间
domInteractive浏览器把document.readyState设置为“interactive”的时间点,DOM树创建结束
domLoading浏览器把document.readyState设置为“loading”的时间点,开始构建dom树的时间点
domainLookupStart返回浏览器开始DNS查询的时间,如果此请求没有DNS查询过程,如长连接、资源cache、甚至是本地资源等,那么就返回fetchStart的值
domainLookupEnd返回浏览器结束DNS查询的时间,如果没有DNS查询过程,同上
fetchStart发起获取当前文档的时间点,个人理解是浏览器收到发起页面请求的时间点
loadEventStart文档触发load事件的时间
loadEventEnd文档出发load事件结束时的时间
navigationStart从同一个浏览器上下文的上一个文档卸载(unload)结束时的时间
redirectStart第一个HTTP重定向开始时的时间
redirectEnd最后一个HTTP重定向完成时(也就是说是HTTP响应的最后一个比特直接被收到的时间)的时间
requestStart浏览器向服务器发出HTTP请求的时间(注意没有requestEnd
responseStart浏览器开始接收第一个字节数据的时间,数据可能来自于服务器、缓存、或本地资源
responseEnd浏览器接收最后一个字节数据的时间,或连接被关闭的时间
secureConnectionStart浏览器与服务器开始安全链接的握手时的时间
unloadEventStart卸载上一个文档开始的时间
unloadEventEnd卸载上一个文档结束的时间

有了Performance.timing这个API,便可以通过它的属性来计算我们需要的性能指标,比如DNS查询耗时白屏时间domready等等,如下

  1. DNS查询耗时 = domainLookupEnd - domainLookupStart
  2. TCP链接耗时 = connectEnd - connectStart
  3. 请求耗时 = responseEnd - requestStart
  4. 解析dom树耗时 = domComplete - domInteractive
  5. 白屏时间 = domLoading - navigationStart
  6. domready时间 = domContentLoadedEventEnd - fetchStart
  7. onload时间 = loadEventEnd - loadEventStart
  8. 整个页面加载时间 = loadEventEnd -navigationStart

1.1、计算性能工具类实现

通过上面介绍的性能指标、对象属性来实现工具类: time.js

(function () {
  function handleAddListener(type, fn) {
    if (window.addEventListener) {
      window.addEventListener(type, fn);
    } else {
      window.attachEvent(`on${type}`, fn);
    }
  }
  function getTiming() {
    try {
      const time = performance.timing;
      var timingObj = {};
      const loadTime = (time.loadEventEnd - time.loadEventStart) / 1000;
      if (loadTime < 0) {
        setTimeout(function () {
          getTiming();
        }, 200);
        return;
      }
      timingObj['重定向时间'] = (time.redirectEnd - time.redirectStart) / 1000;
      timingObj['DNS解析时间'] =
        (time.domainLookupEnd - time.domainLookupStart) / 1000;
      timingObj['TCP完成握手时间'] =
        (time.connectEnd - time.connectStart) / 1000;
      timingObj['HTTP请求响应完成时间'] =
        (time.responseEnd - time.requestStart) / 1000;
      timingObj['DOM开始加载前所花费时间'] =
        (time.responseEnd - time.navigationStart) / 1000;
      timingObj['DOM加载完成时间'] =
        (time.domComplete - time.domLoading) / 1000;
      timingObj['DOM结构解析完成时间'] =
        (time.domInteractive - time.domLoading) / 1000;
      timingObj['脚本加载时间'] =
        (time.domContentLoadedEventEnd - time.domContentLoadedEventStart) /
        1000;
      timingObj['onload事件时间'] =
        (time.loadEventEnd - time.loadEventStart) / 1000;
      timingObj['**白屏时间**'] = (time.domLoading - time.fetchStart) / 1000;
      timingObj['页面完全加载时间'] =
        timingObj['重定向时间'] +
        timingObj['DNS解析时间'] +
        timingObj['TCP完成握手时间'] +
        timingObj['HTTP请求响应完成时间'] +
        timingObj['DOM结构解析完成时间'] +
        timingObj['DOM加载完成时间'];
      Object.keys(timingObj).forEach((key) => {
        console.log(`${key}:${timingObj[key]}秒(s)`);
      });
      console.log(performance, performance.timing);
    } catch (e) {
      console.log(e);
      console.log(timingObj);
      console.log(performance, performance.timing);
    }
  }
  handleAddListener('load', getTiming);
})();

然后在inde.html的最后引入time.js

image.png 然后就可以在我们的开发者工具的控制台监听首页的性能了,如下图:

image.png

2、performance.getEntries()

这个API能帮我们获得资源的请求时间,包括JS、CSS、图片等

image.png

如上图所示,可以看到这个API请求返回的是一个数组,这个数组包括整个页面所有的资源加载,上图打开了一个其中一个资源,可以看到如下信息:

  1. entryType:类型为resource
  2. name:资源的url
  3. initiatorType:资源是link
  4. 资源时间:duration的值,是responseEnd - startTime得到的

3、performance.memory

这个API主要是得到浏览器内存情况

image.png

  1. jsHeapSizeLimit:内存大小限制
  2. totalJSHeapSize:可使用的内容
  3. userdJSHeapSize:已使用的内容
    userdJSHeapSize表示所有被使用的JS堆栈内存,totalJSHeapSize可使用的JS堆栈内存,如果userdJSHeapSize的值大于totalJSHeapSize,就可能出现内存泄漏