按指标衡量
完...
衡量前端产品性能有多个指标,我们解读一下chrome开发工具为我们提供的指标:
1. Chrome Dev Tools
Network标签
访问爱奇艺首页:
421 requests - 网络请求数
15.1 MB transferred - 数据传输量(压缩)
18.2 MB resources - 数据原始大小
Finish 3.91 s - 最后请求完成时间
DOMContentLoaded: 758ms - DOM完全加载及解析事件触发时间
Load: 3.83 s - 页面加载完成触发时间
虽然有几百个请求,但页面加载只用了4秒不到的时间,代表着非常豪华的硬件网络,赤裸裸地透露着有钱人的气质。
以上几个指标理解起来都不难, 我们看看在具体的某一个请求中有哪些信息可以参考。选中任意行并将鼠标移到waterfall
Queued at - 请求入队列时间
Started at 4.67 ms - 请求开始时间,注意,开始并不代表请求发送
Resource Scheduling
Queueing 4.67 ms - 入队耗时
Connection Start
Stalled 0.62 ms - 请求被挂起,会有多种原因,比如要是缓存命中的话,请求就不会被发送了
DNS Lookup 8.65 ms - DNS解析耗时
Initial connection 45.22 ms - 初次连接耗时
SSL 45.22 ms - SSL 耗时
Request/Response
Request sent 0.37 ms - 请求发送耗时
Waiting (TTFB)0.44 ms - Time to First Byte 首字节耗时
Content Download - 资源下载时间
Performance标签
Google 还提出了一些以用户为中心的指标 - user centric metrics,优秀的企业就是会搞事情。
让我们从Network切换到Performance标签,再访问爱奇艺首页:
FP - First Paint - 首次渲染,就是说开始渐进式解析DOM结构并在页面上有所体现了
FCP - First Contentful Paint - 首次内容渲染,此时页面已经包含了一些文字,图标等
DCL - DOMContentLoaded - DOM完全加载及解析事件触发
FMP - First Meaningful Paint - 首次有效渲染,此时页面已经包含了更多文字,图标等
LCP - Large Content Paint - 革命就要胜利了
L - Load 页面加载完成
指标有点多,就用户体验而言,实际项目中我们多参考FP/FCP, 可以理解为白屏时间。
另外还有一个指标叫TTI - Time to Interactive,可交互时间,它描述这样一个时间点
- 最后一个长任务完成(耗时大于等于50毫秒的任务)
- 随后有5秒的网络和主线程空闲
这一项指标要做得准确比较困难,目前chrome还没有集成。 有兴趣的同学可以了解一下github GoogleChromeLabs/tti-polyfill 项目。
以上是chrome开发工具为我们提供的性能观测指标,此外我们还能通过javascript 在代码层面做一些性能监测,这需要了解一下可怕的 performance API。
2. Performance API
“It's part of the High Resolution Time API, but is enhanced by the Performance Timeline API, the Navigation Timing API, the User Timing API, and the Resource Timing API.”
这段洋文理解起来有点费劲,我们先看盗图:
Performance API 是 High Resolution Time(高精度时间) API的子集。
Performance Timeline API 是对Performance API的扩展,它提供了访问其他API的统一入口。可以这么理解,Navigation/User/Resource/Frame/Paint Timing API 都是指标,Performance Timeline API 是访问这些指标的统一入口。
当我们提到Performance Timeline API 可以狭义的理解为浏览器performance 对象中以下三个主要方法:
- getEntries()
- getEntriesByType()
- getEntriesByName()
ps: 你可能知道,performance 中还有两个对象 timing 和 navigation,通过这两个对象可以绕开performance timeline API 直接访问部分指标,这是早期的访问方式,已不建议使用。
getEntries()
获取所有项
getEntriesByType()
根据type获取,可选的type有以下几种:
- navigation
- resource
- mark
- measure
- paint
- longtask
- frame
-
navigation - Navigation Timing API
获取浏览器上下文,比如DNS查询时间,TCP连接时间。
-
resource - Resource Timing API
获取资源连接信息。
mark - User Timing API
获取mark,配合performance.mark() 使用。
performance.mark(‘alpha’)
- measure - User Timing API
获取 measure,配合performance.mark(), performance.measure() 使用。
performance.mark(“alpha’)
performance.mark(“beta’)
performance.measure(“time”,”alpha”,”beta”)
-
paint - Paint Timing API
获取FP,FCP 时间。
longtask - Long Tasks API
获取耗时大于等于50毫秒的任务。
performance.getEntriesByType(‘longtask’)
- frame - Framing Timing API
获取帧变化信息,变化可由以下几种情况触发
- DOM变化
- resizing
- scrolling
- rendering
- css 动画
此API似乎还未在chrome上实现。
getEntriesByName()
根据名称获取。
performance.getEntriesByName("first-paint")
performance.mark("alpha")
performance.getEntriesByName("alpha")
Performance.measure(‘time’,"alpha")
performance.getEntriesByName("time")
performance.getEntriesByName("https://www.a.com/logo.png")
3. 指标监测
通过performance timeling api 我们可以计算以下指标:
t = performance.getEntriesByType('navigation')[0]
//重定向耗时
times.redirectTime = t.redirectEnd - t.redirectStart;
//DNS查询耗时
times.dnsTime = t.domainLookupEnd - t.domainLookupStart;
//TTFB
times.ttfbTime = t.responseStart - t.navigationStart;
//DNS缓存耗时
times.appcacheTime = t.domainLookupStart - t.fetchStart;
//卸载页面耗时
times.unloadTime = t.unloadEventEnd - t.unloadEventStart;
//tcp连接耗时
times.tcpTime = t.connectEnd - t.connectStart;
//request请求耗时
times.reqTime = t.responseEnd - t.responseStart;
//解析dom树耗时
times.analysisTime = t.domComplete - t.domInteractive;
//白屏时间
times.blankTime = t.domInteractive - t.fetchStart;
//DOM加载耗时
times.domReadyTime = t.domContentLoadedEventEnd - t.fetchStart;
4. 响应式监测
通过PerformanceObserver监测由交互、定时任务引起的变化,比如图片懒加载。
var observer = new PerformanceObserver(list => {
list.getEntries().forEach(entry => {
// Display each reported measurement on console
if (console) {
console.log("Name: " + entry.name +
", Type: " + entry.entryType +
", Start: " + entry.startTime +
", Duration: " + entry.duration + "\n");
}
})
});
observer.observe({entryTypes: ['resource']});
参考
10分钟彻底搞懂前端页面性能监控
Performance Observer: Efficient Access to Performance Data
Breaking Down the Performance API
爱奇艺