Articles
Articles copied to clipboard
前端性能监控 Performance
Performance
接口可以获取到当前页面中与性能相关的信息。它是 High Resolution Time API 的一部分,同时也融合了 Performance Timeline API、Navigation Timing API、 User Timing API 和 Resource Timing API。
该类型的对象可以通过调用只读属性 Window.performance
来获得。
// 兼容性写法
const performance = window.performance || window.msPerformance || window.webkitPerformance;
也可以通过**
Performance
**获取Web Worker
执行性能。
Performance 属性
-
Performance.navigation
-PerformanceNavigation
对象提供了在指定的时间段里发生的操作相关信息,包括页面是加载还是刷新、发生了多少次重定向等等。Not available in workers. -
Performance.timing
-PerformanceTiming
对象包含延迟相关的性能信息。Not available in workers.Navigation Timing Level 2 草案中,已经废弃了 PerformanceTiming 接口,并且提供了新的接口 PerformanceNavigationTiming 代替其功能,performance.getEntriesByType("navigation") 获取。
-
performance.memory
- 其是 Chrome 添加的一个非标准扩展,这个属性提供了一个可以获取到基本内存使用情况的对象。不应该使用这个非标准的 API。-
jsHeapSizeLimit
上下文内可用堆的最大体积,以字节计算。
-
totalJSHeapSize
已分配的堆体积,以字节计算。
-
usedJSHeapSize
当前 JS 堆活跃段(segment)的体积,以字节计算。
-
-
Performance.timeOrigin
- 返回性能测量开始时的时间的高精度时间戳。
Performance 方法
-
Performance.clearMarks()
- 将给定的 mark 从浏览器的性能输入缓冲区中移除。 -
Performance.clearMeasures()
- 将给定的 measure 从浏览器的性能输入缓冲区中移除。 -
Performance.clearResourceTimings()
- 从浏览器的性能数据缓冲区中移除所有entryType
是 "resource
" 的performance entries
。 -
Performance.getEntries()
- 基于给定的 filter 返回一个PerformanceEntry
对象的列表。 -
Performance.getEntriesByName()
- 基于给定的 name 和 entry type 返回一个PerformanceEntry
对象的列表。 -
Performance.getEntriesByType()
- 基于给定的 entry type 返回一个PerformanceEntry
对象的列表 -
Performance.mark()
- 根据给出 name 值,在浏览器的性能输入缓冲区中创建一个相关的timestamp
-
Performance.measure()
- 在浏览器的指定 start mark 和 end mark 间的性能输入缓冲区中创建一个指定的timestamp
-
Performance.now()
- 返回一个表示从性能测量时刻开始经过的毫秒数DOMHighResTimeStamp
-
Performance.setResourceTimingBufferSize()
- 将浏览器的资源 timing 缓冲区的大小设置为 "resource
"type
performance entry
对象的指定数量 -
Performance.toJSON()
- 其是一个 JSON 格式转化器,返回Performance
对象的 JSON 对象
performance.navigation 对象
除了时间信息,performance还可以提供一些用户行为信息,主要都存放在 performance.navigation
对象上面。
它有两个属性:
(1)performance.navigation.type
该属性返回一个整数值,表示网页的加载来源,可能有以下4种情况:
-
0:网页通过点击链接、地址栏输入、表单提交、脚本操作等方式加载,相当于常数performance.navigation.TYPE_NAVIGATENEXT。
-
1:网页通过“重新加载”按钮或者location.reload()方法加载,相当于常数performance.navigation.TYPE_RELOAD。
-
2:网页通过“前进”或“后退”按钮加载,相当于常数performance.navigation.TYPE_BACK_FORWARD。
-
255:任何其他来源的加载,相当于常数performance.navigation.TYPE_UNDEFINED。
(2)performance.navigation.redirectCount
该属性表示当前网页经过了多少次重定向跳转。
performance.timing 对象
performance
对象的 timing
属性指向一个对象,它包含了各种与浏览器性能有关的时间数据,提供浏览器处理网页各个阶段的耗时。比如,performance.timing.navigationStart
就是浏览器处理当前网页的启动时间。
performance.timing
对象包含以下属性(全部为只读):
- navigationStart:当前浏览器窗口的前一个网页关闭,发生unload事件时的Unix毫秒时间戳。如果没有前一个网页,则等于fetchStart属性。
- unloadEventStart:如果前一个网页与当前网页属于同一个域名,则返回前一个网页的unload事件发生时的Unix毫秒时间戳。如果没有前一个网页,或者之前的网页跳转不是在同一个域名内,则返回值为0。
- unloadEventEnd:如果前一个网页与当前网页属于同一个域名,则返回前一个网页unload事件的回调函数结束时的Unix毫秒时间戳。如果没有前一个网页,或者之前的网页跳转不是在同一个域名内,则返回值为0。
- redirectStart:返回第一个HTTP跳转开始时的Unix毫秒时间戳。如果没有跳转,或者不是同一个域名内部的跳转,则返回值为0。
- redirectEnd:返回最后一个HTTP跳转结束时(即跳转回应的最后一个字节接受完成时)的Unix毫秒时间戳。如果没有跳转,或者不是同一个域名内部的跳转,则返回值为0。
- fetchStart:返回浏览器准备使用HTTP请求读取文档时的Unix毫秒时间戳。该事件在网页查询本地缓存之前发生。
- domainLookupStart:返回域名查询开始时的Unix毫秒时间戳。如果使用持久连接,或者信息是从本地缓存获取的,则返回值等同于fetchStart属性的值。
- domainLookupEnd:返回域名查询结束时的Unix毫秒时间戳。如果使用持久连接,或者信息是从本地缓存获取的,则返回值等同于fetchStart属性的值。
- connectStart:返回HTTP请求开始向服务器发送时的Unix毫秒时间戳。如果使用持久连接(persistent connection),则返回值等同于fetchStart属性的值。
- connectEnd:返回浏览器与服务器之间的连接建立时的Unix毫秒时间戳。如果建立的是持久连接,则返回值等同于fetchStart属性的值。连接建立指的是所有握手和认证过程全部结束。
- secureConnectionStart:返回浏览器与服务器开始安全链接的握手时的Unix毫秒时间戳。如果当前网页不要求安全连接,则返回0。
- requestStart:返回浏览器向服务器发出HTTP请求时(或开始读取本地缓存时)的Unix毫秒时间戳。
- responseStart:返回浏览器从服务器收到(或从本地缓存读取)第一个字节时的Unix毫秒时间戳。
- responseEnd:返回浏览器从服务器收到(或从本地缓存读取)最后一个字节时(如果在此之前HTTP连接已经关闭,则返回关闭时)的Unix毫秒时间戳。
- domLoading:返回当前网页DOM结构开始解析时(即Document.readyState属性变为“loading”、相应的readystatechange事件触发时)的Unix毫秒时间戳。
- domInteractive:返回当前网页DOM结构结束解析、开始加载内嵌资源时(即Document.readyState属性变为“interactive”、相应的readystatechange事件触发时)的Unix毫秒时间戳。
- domContentLoadedEventStart:返回当前网页DOMContentLoaded事件发生时(即DOM结构解析完毕、所有脚本开始运行时)的Unix毫秒时间戳。
- domContentLoadedEventEnd:返回当前网页所有需要执行的脚本执行完成时的Unix毫秒时间戳。
- domComplete:返回当前网页DOM结构生成时(即Document.readyState属性变为“complete”,以及相应的readystatechange事件发生时)的Unix毫秒时间戳。
- loadEventStart:返回当前网页load事件的回调函数开始时的Unix毫秒时间戳。如果该事件还没有发生,返回0。
- loadEventEnd:返回当前网页load事件的回调函数运行结束时的Unix毫秒时间戳。如果该事件还没有发生,返回0。
计算性能指标
- DNS查询耗时 = domainLookupEnd - domainLookupStart
- TCP链接耗时 = connectEnd - connectStart
- request请求耗时 = responseEnd - responseStart
- 解析dom树耗时 = domComplete - domInteractive
- domready时间 = domContentLoadedEventEnd - fetchStart
- 首屏渲染时间、首次有内容渲染时间 performance.getEntriesByType('paint') https://w3c.github.io/paint-timing/
- onload时间 = loadEventEnd - fetchStart
// 计算加载时间
function getPerformanceTiming () {
const performance = window.performance || window.msPerformance || window.webkitPerformance;
if (!performance) {
// 当前浏览器不支持
console.log('你的浏览器不支持 performance 接口');
return;
}
const t = performance.timing;
const times = {};
//【重要】页面加载完成的时间
//【原因】这几乎代表了用户等待页面可用的时间
times.loadPage = t.loadEventEnd - t.navigationStart;
//【重要】解析 DOM 树结构的时间
//【原因】反省下你的 DOM 树嵌套是不是太多了!
times.domReady = t.domComplete - t.responseEnd;
//【重要】重定向的时间
//【原因】拒绝重定向!比如,http://example.com/ 就不该写成 http://example.com
times.redirect = t.redirectEnd - t.redirectStart;
//【重要】DNS 查询时间
//【原因】DNS 预加载做了么?页面内是不是使用了太多不同的域名导致域名查询的时间太长?
// 可使用 HTML5 Prefetch 预查询 DNS ,见:[HTML5 prefetch](http://segmentfault.com/a/1190000000633364)
times.lookupDomain = t.domainLookupEnd - t.domainLookupStart;
//【重要】读取页面第一个字节的时间
//【原因】这可以理解为用户拿到你的资源占用的时间,加异地机房了么,加CDN 处理了么?加带宽了么?加 CPU 运算速度了么?
// TTFB 即 Time To First Byte 的意思
// 维基百科:https://en.wikipedia.org/wiki/Time_To_First_Byte
times.ttfb = t.responseStart - t.navigationStart;
//【重要】内容加载完成的时间
//【原因】页面内容经过 gzip 压缩了么,静态资源 css/js 等压缩了么?
times.request = t.responseEnd - t.requestStart;
//【重要】执行 onload 回调函数的时间
//【原因】是否太多不必要的操作都放到 onload 回调函数里执行了,考虑过延迟加载、按需加载的策略么?
times.loadEvent = t.loadEventEnd - t.loadEventStart;
// DNS 缓存时间
times.appcache = t.domainLookupStart - t.fetchStart;
// 卸载页面的时间
times.unloadEvent = t.unloadEventEnd - t.unloadEventStart;
// TCP 建立连接完成握手的时间
times.connect = t.connectEnd - t.connectStart;
return times;
}
performance.mark()
mark
方法用于为相应的视点做标记。
window.performance.mark('mark_fully_loaded');
clearMarks
方法用于清除标记,如果不加参数,就表示清除所有标记。
window.peformance.clearMarks('mark_fully_loaded');
window.performance.clearMarks();
performance.getEntries()
浏览器获取网页时,会对网页中每一个对象(脚本文件、样式表、图片文件等等)发出一个HTTP请求。performance.getEntries
方法以数组形式,返回这些请求的时间统计信息,有多少个请求,返回数组就会有多少个成员。
由于该方法与浏览器处理网页的过程相关,所以只能在浏览器中使用。
window.performance.getEntries()[0]
// PerformanceResourceTiming {
// responseEnd: 4121.6200000017125,
// responseStart: 4120.0690000005125,
// requestStart: 3315.355000002455,
// ...
// }
上面代码返回第一个 HTTP请求(即网页的HTML源码)的时间统计信息。该信息以一个高精度时间戳的对象形式返回,每个属性的单位是毫秒(milliseconds)。
性能监测对象
PerformanceObserver
用于监测性能度量事件,在浏览器的性能时间轴记录下一个新的 performance entries 的时候将会被通知 。
此特性在 Web Worker 中可用。
-
创建并返回一个新的
PerformanceObserver
对象。 -
指定监测的
entry types
的集合。 当performance entry
被记录并且是指定的entryTypes
之一的时候,性能观察者对象的回调函数会被调用。 -
PerformanceObserver.disconnect()
性能监测回调停止接收 性能条目。
// 测量 Long Task
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
// TODO...
console.log(entry);
}
});
observer.observe({entryTypes: ['longtask']});
Other Resources
改善页面性能 - 开发者需要了解的 Performance API 标准
performance timing 准备要废弃了,用什么api替代呢
performance timing 准备要废弃了,用什么api替代呢
好问题,现在 chrome 还是支持的,到底啥时候废弃,替代品又是啥呢?
performance timing 准备要废弃了,用什么api替代呢 @huoguozhang @reng99
performance.getEntriesByType('navigation')