目录
2.问题现状
5.2 性能数据格式(High Resolution Time Level 2)
5.3 获取数据方式(Performance Timeline Level 2)
1.前言
为了便于量化页面性能指标数据,量化页面性能优化措施达到的优化效果,以及向合作方提供准确可靠的性能数据报告,研发侧需要对现有性能数据采集的兼容性、功能性进行调研,便于后续制定数据采集方案。
2.问题现状
性能数据目前在前端业务方面十分重要,但是结果却是处于无从下手的阶段,基本是零,系统用户以及客户及内部需求都存在需要可度量的性能数据的诉求。
3.术语说明
什么是前端的性能数据,简而言之,就是 window.performance。前端的性能数据采集,就是将需要的 performance 数据,获取并上报到自己的后台或日志系统中,后续还需要再加以分析监控处理,这里只涉及到 performance 相关的数据采集。
4.数据采集
performance 中性能数据采集方式:
- 主动获取 - getEntry 系列方法
- 被动监听 - Observer 方法
- 原始方法 - performance.timing
4.1 主动获取
performance 下挂了三个方法可以用于通过 get 方式获取性能数据,获取到的性能数据都是 PerformanceEntry 类型,规范要求,后续所有不同类型的性能数据实现都要求实现如下接口,要求可以被如下接口 get 到,并且数据类型继承 PerformanceEntry。新的性能 API 到要基于此实现。
使用示例如下:
4.2 被动监听
可以通过 PerformanceObserver 注册监听函数,获取性能数据,示例如下:
4.3 performance.timing
若以上两种方式浏览器都不支持,可以通过 performance 对象的 timing 属性,获取较早版本的导航类性能数据。此API较为早期,采集到的数据格式是时间戳格式,兼容性较好,但时间精度可能无法满足要求。
4.4 问题说明
资源类的性能数据有数量限制,若超出限制,会触发 performance.onresourcetimingbufferfull,需要通过 Performance.clearResourceTimings(),清理性能数据 buffer,否则新的资源类性能数据就不会被记录,也就取不到了。
5.行业规范现状
网上真的有很多关于 performance 的帖子,常见的也有几张页面加载时间节点与流程对应的示意图,但是不太统一,看的人眼花缭乱,不太清楚什么是什么,比如 chrome 中获取到的performance,为什么外层有 performace.timing,entry 内还能取到类似的 navigationtiming,为什么有字段略微出入的 navigation 流程示意图。下面说明一下性能数据相关规范,便于后续理解相关API。
性能数据相关规范一览图:
5.1 性能数据分类
性能数据类型主要有:
- navigation - 导航类,页面打开的整体过程数据
- resource - 页面中的资源,比如 css js img ajax 请求,等mark/measure 用户自己根据业务需求按需打点的性能数据
- paint - 渲染类
5.2 性能数据格式(High Resolution Time Level 2)
提到性能数据,得先说一说,性能数据的格式。上述说到的导航类性能数据 navigation,最原始的方式是通过 performance.timing ,从截图可以看出,包括 performance.timeOrigin 在内的数据都是时间戳格式的,这个时间精度在某些情况下可能并不能满足人们对于性能数据的测量需求,因此 W3C 提出了高进度时间戳的定义 DOMHighResTimeStamp,所有后续的性能数据规范返回的时间都要求基于此 API 定义实现,返回高精度时间戳。
资源类数据的原始时间戳格式与高进度时间戳格式对比:
5.3 获取数据方式(Performance Timeline Level 2)
基于高精度时间戳的定义,performance timeline 定义了获取数据的方法,其中包括 getEntry 接口,及 PerformanceObserver 的定义。有了时间的定义,格式,获取方式,下面就是不同类型的性能数据具体实现了。
5.4. NavigationTiming
Navigation Timing Level 2 定义了导航类性能数据的格式。定义的时间字段与加载过程的对应关系如下,这张图是第二版规范上带的,如果你看到另一张图,那是第一版规范上的,不要懵。
navigation 可以通过 observer navigation 类型的数据获取。
若 observer 不支持,可以通过 getEntry 的方式获取(坑点:浏览器可能支持 getEntry 的方式获取数据,但是取不到 navigation 类型的,只能取到 resource,此处需要做好异常处理)
若上述两种方式取不到,那就走原始方式 performance.timing 取吧。
5.5. ResourceTiming
resource 是资源类性能数据,其中包括 页面的 css js img 文件加载,ajax 请求,等。
由 resource 涉及到的数据范围可想而知,resource 数据会超级多,浏览器也不可能无限制的记录。因此有个 buffer 的概念。
设置 buffer : Performance.setResourceTimingBufferSize()
监听 buffer 满事件: Performance.onresourcetimingbufferfull
清除 buffer: Performance.clearResourceTimings()
resource 存在两版 API,第一版默认 buffersize 为最小 150,第二版建议 buffersize 最小为 250。
另外,buffer 类的性能数据要想获取到除了 PerformanceEntry 定义之外的 tcp http dns 等过程的数据,会有跨域问题,若需要采集跨域相关数据,需要添加 资源跨域头 Timing-Allow-Origin。(备注,若 ajax 类的性能数据需要获取服务端的耗时,可以通过 ServerTiming 规范规定的 Server-Timing 头获取服务端数据 serverTiming, 此时间格式的获取也受跨域头限制,若请求为跨域请求,两个响应都需要有,浏览器才可以采集到服务端耗时 serverTiming)
6.总结
页面端可以使用性能数据采集API做到的功能包括:
- 通用数据采集:
- 页面导航类加载性能数据;
- 页面所有资源的加载时间数据(这里的资源包括 css js img ajax请求等);
- 页面的渲染数据(包括fp、fcp)
- (2) 定制数据采集:
页面可以根据业务需要使用性能API自行打点采集。
其中,需要注意的问题有:
- 导航类加载性能数据采集的格式包括两个W3C规范版本:普通时间戳与高精度时间戳,采集数据时需要注意处理。
- 资源类加载时间的处理存在两个W3C规范版本,对于资源缓存的buffer大小存在不同定义,采集资源类性能数据时,需要注意buffer溢出清空处理。
7.官方规范文档
以下标明了官方相关规范文档的主要内容:
- [High Resolution Time Level 2](https://www.w3.org/TR/2019/REC-hr-time-2-20191121/) 高精度时间戳 DOMHighResTimeStamp 定义
- [Performance Timeline](https://www.w3.org/TR/2013/REC-performance-timeline-20131212/)
- [Performance Timeline Level 2](https://www.w3.org/TR/2019/WD-performance-timeline-2-20191024/)
2的主要内容如下:
- PerformanceEntry 接口定义
- Performance.getEntries()
- Performance.getEntriesByType()
- Performance.getEntriesByName()