性能分析(二)好戏开始:数据从何而来

824 阅读4分钟

上回书说到,前戏做足,于是我们采取了rollup来打包我们的js-sdk,那么工具都有了,就要准备正事了。

本篇内容是连续,建议收藏,开篇会有前几篇链接。开此专题会带领大家如何开发一个真正的,有意义的性能分析系统,而不是单纯的炫技。

性能分析,首要的就是数据,本期就带大家在数据的海洋里捞针。

前情回顾:性能分析(一)前戏:用 rollup 打包一个 js-sdk

收集数据

Performance - Web APIs | MDN

PerformanceAPI 是使用最多的,通过这个 api,我们可以采集到页面的很多数据,例如domCompleteDOM 完成时间,domInteractiveDOM 可交互时间等等。

const [pagePerformance] = performance.getEntries();
console.log(pagePerformance);

可以看到,pagePerformance是个非常大的对象,我们来分析一下这个对象。

参数 翻译 含义
startTime 开始时间 表示整个 document 资源开始的时间,一般为 0
redirectStart 重定向时间 表示开始重定向的时间(如果没有则为 0)
redirectEnd 重定向结束时间 表示结束重定向的时间(如果没有则为 0)
redirectCount 重定向次数 表示产生重定向的次数
fetchStart 请求开始时间 表示客户端开始准备请求的时间
domainLookupStart 建立DNS开始 表示DNS开始建立的时间
domainLookupEnd DNS建立结束 表示DNS建立成功的时间
connectStart 建立TCP开始 表示TCP连接开始建立的时间
secureConnectionStart HTTPS建立时间 如果有HTTPS,则记录HTTPS建立开始时间
connectEnd TCP建立结束 表示TCP连接建立成功的时间
requestStart 资源开始请求时间 表示资源开始请求的时间
responseStart 首字节到达时间ttfb 表示服务端返回第一个字节记录的时间
responseEnd 资源完全抵达时间 表示资源完全抵达,dom开始渲染
domInteractive dom可交互时间 表示dom渲染进入可交互时间
domContentLoadedEventStart domContentLoaded 事件触发时间 表示 domContentLoaded 事件触发的时间
domContentLoadedEventEnd domContentLoaded 事件完成触发时间 表示 domContentLoaded 事件结束触发的时间
domComplete dom完成的时间 表示dom完成的时间
nextHopProtocol http 协议 -

这一个大表看下来,大家会觉得,东西太乱太杂了,是的,因为没有经过加工的数据,就是杂乱无章的,所以我们稍微整理一下。首先我们需要知道,页面加载的流程是什么,经过我不懈努力的寻找,得到下面这个图

按照上图,我们可以得到新的结构(这里的时间是毫秒时间,eg: 14.644999988377094 ms)

参数 翻译 算法
startTime 开始时间 startTime || fetchStart
redirect 重定向时间 redirectEnd-redirectStart
dns DNS 建立时间 domainLookupEnd-domainLookupStart
tcp TCP 建立时间 connectEnd-connectStart
response 资源加载时间 responseEnd-requestStart(注意这里是response-request)
interactive 可交互时间 domInteractive-responseEnd
content 内容加载时间 domContentLoadedEventEnd-domContentLoadedEventStart
complete dom 完成时间 domComplete-responseEnd
nextHopProtocol http 协议 -

新的结构看起来就舒服多了,我们可以看到,有些数据是表示间隔,有些数据则是同一个timeline,那么这张图,我们得到一个新的性能分析timing图如下所示:

上下其手

既然知道需要收集什么数据,我们就开始着手行动

  1. 收集我们上一节提到的perormance timing数据
  2. 收集一些额外的物理数据,例如 浏览器信息、操作系统信息等
  3. 制定上报策略,环境隔离

浏览器信息 & 操作系统信息

通过user-agent我们可以解析上述信息,这里我提供给大家两个不错的解析工具,当然网上也可以搜到很多相关资料,暂不赘述。

UAParser.js A JavaScript-based User-Agent string parser. Can be used either in browser (client-side) or in node.js (server-side) environment.

useragent.js A User-agent analyze project.

分辨率信息

利用window.screen提供的widthheight即可

开工

import UAParser from 'ua-parser-js';
import axios from 'axios';

class FirstPaintTiming {
  get requestUrl() {
    return (
      {
        test: 'https://ihap.txdy.test.fakeurl/api/v1/page',
        production: 'https://ihap.txdy.production.fakeurl/api/v1/page',
      }[this.env] || false
    );
  }

  constructor(options = { env: 'test' }) {
    this.env = options.env;
  }

  upload2Server() {
    try {
      requestUrl && axios.post(requestUrl, [this.getPageInfo()]);
    } catch {}
  }

  getPageInfo() {
    return {
      ...this._getPagePerformance(),
      ...this._getPhysics(),
    };
  }

  _getPagePerformance() {
    const [pagePerformance] = performance.getEntries();
    return {
      startTime: pagePerformance.startTime || pagePerformance.fetchStart,
      redirect: pagePerformance.redirectEnd - pagePerformance.redirectStart,
      dns: pagePerformance.domainLookupEnd - pagePerformance.domainLookupStart,
      tcp: pagePerformance.connectEnd - pagePerformance.connectStart,
      response: pagePerformance.responseEnd - pagePerformance.requestStart,
      interactive: pagePerformance.domInteractive - pagePerformance.responseEnd,
      content:
        pagePerformance.domContentLoadedEventEnd - pagePerformance.domContentLoadedEventStart,
      complete: pagePerformance.domComplete - pagePerformance.responseEnd,
      nextHopProtocol: pagePerformance.nextHopProtocol,
    };
  }

  _getPhysics() {
    const uaParser = new UAParser().getResult();

    const { name: browserName, version: browserVersion } = uaParser.browser;
    const { name: osName, version: osVersion } = uaParser.os;
    return {
      os: `${browserName}${browserVersion}`,
      browser: `${osName}${osVersion}`,
    };
  }
}

本期总结

本期,我们讲了数据从何而来以及数据采集的方法,但是实现一个性能分析的js-sdk我们目前仍然缺少一些关键的内容:

  1. 上报策略制定
  2. 数据上报之后如何分析
  3. 统一上报接口
  4. 对接外网出口(验签体系)
  5. npm 包管理,beta/正式版本管理
  6. (extra) 资源数据分析模块
  7. (extra) 如何对业务产生有效的影响?如何利用性能分析系统增强业务支持。

下期预告

下次我们会进入慢热节奏,着重讲述上报策略与统一上报接口的内容。请大家拭目以待!我是 ihap 技术黑洞的 ihap 肥少,欢迎点赞打赏,也请大家关注我们的公众号,ihap 技术黑洞。

参考文献

www.cnblogs.com/lzbk/p/6330… 前端页面性能参数搜集 www.w3.org/TR/navigati… Navigation Timing developer.mozilla.org/en-US/docs/… Performance - Web APIs | MDN