window.performance
是W3C性能小组引入的新的API,目前IE9以上的浏览器都支持。一个performance
对象的完整结构如下图所示:
memory 字段
memory
字段代表JavaScript对内存的占用。
navigation 对象
navigation
字段统计的是一些网页导航相关的数据。
redirectCount
navigation.redirectCount
网页经过了多少次重定向跳转,但是这个接口有同源策略限制,即仅能检测同源的重定向;
type
navigation.type
返回值应该是0,1,2 中的一个。分别对应三个枚举值:
- 0:网页通过点击链接、地址栏输入、表单提交、脚本操作等方式加载,相当于常数
performance.navigation.TYPE_NAVIGATENEXT
。 - 1:网页通过“重新加载”按钮或者
location.reload()
方法加载,相当于常数performance.navigation.TYPE_RELOAD
。 - 2:网页通过“前进”或“后退”按钮加载,相当于常数
performance.navigation.TYPE_BACK_FORWARD
。 - 255:任何其他来源的加载,相当于常数
performance.navigation.TYPE_UNDEFINED
。
timing 对象
timing
字段它包含了网络、解析等一系列的时间数据,其整体结构如下图所示:
timing
字段提供浏览器处理网页各个阶段的耗时。比如,performance.timing.navigationStart
就是浏览器处理当前网页的启动时间。
得到页面加载的耗时、域名解析的耗时、TCP连接的耗时、读取页面第一个字节之前的耗时
var t = performance.timing;
var pageloadtime = t.loadEventStart - t.navigationStart;
var dns = t.domainLookupEnd - t.domainLookupStart;
var tcp = t.connectEnd - t.connectStart;
var ttfb = t.responseStart - t.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。
网页加载整个过程的耗时的计算方法如下:
var t = performance.timing;
var pageLoadTime = t.loadEventEnd - t.navigationStart;
DNS查询耗时、白屏时间、domready等。如下:
- DNS查询耗时 = domainLookupEnd - domainLookupStart
- TCP链接耗时 = connectEnd - connectStart
- request请求耗时 = responseEnd - responseStart
- 解析dom树耗时 = domComplete - domInteractive
- 白屏时间 = domloadng - fetchStart
- domready时间 = domContentLoadedEventEnd - fetchStart
- onload时间 = loadEventEnd - fetchStart
var timing = window.performance && window.performance.timing;
var navigation = window.performance && window.performance.navigation;
//重定向次数:
var redirectCount = navigation && navigation.redirectCount;
//跳转耗时:
var redirect = timing.redirectEnd - timing.redirectStart;
//APP CACHE 耗时:
var appcache = Math.max(timing.domainLookupStart - timing.fetchStart, 0);
//DNS 解析耗时:
var dns = timing.domainLookupEnd - timing.domainLookupStart;
//TCP 链接耗时:
var conn = timing.connectEnd - timing.connectStart;
//等待服务器响应耗时(注意是否存在cache):
var request = timing.responseStart - timing.requestStart;
//内容加载耗时(注意是否存在cache):
var response = timing.responseEnd - timing.responseStart;
//总体网络交互耗时,即开始跳转到服务器资源下载完成:
var network = timing.responseEnd - timing.navigationStart;
//渲染处理:
var processing = (timing.domComplete || timing.domLoading) - timing.domLoading;
//抛出 load 事件:
var load = timing.loadEventEnd - timing.loadEventStart;
//总耗时:
var total = (timing.loadEventEnd || timing.loadEventStart || timing.domComplete || timing.domLoading) - timing.navigationStart;
//可交互:
var active = timing.domInteractive - timing.navigationStart;
//请求响应耗时,即 T0,注意cache:
var t0 = timing.responseStart - timing.navigationStart;
//首次出现内容,即 T1:
var t1 = timing.domLoading - timing.navigationStart;
//内容加载完毕,即 T3:
var t3 = timing.loadEventEnd - timing.navigationStart;
performance.now 方法
performance.now
方法返回当前网页自从performance.timing.navigationStart
到当前时间之间的微秒数(毫秒的千分之一)。也就是说,它的精度可以达到100万分之一秒。
performance.now()
// 23493457.476999998
Date.now() - (performance.timing.navigationStart + performance.now())
// -0.64306640625
上面代码表示,performance.timing.navigationStart
加上performance.now()
,近似等于Date.now()
,也就是说,Date.now()
可以替代performance.now()
。但是,前者返回的是毫秒,后者返回的是微秒,所以后者的精度比前者高1000倍。
通过两次调用performance.now
方法,可以得到间隔的准确时间,用来衡量某种操作的耗时。
var start = performance.now();
doTasks();
var end = performance.now();
console.log('耗时:' + (end - start) + '微秒。');
performance.mark 等方法
用于做标记和清除标记,供用户自定义统计一些数据,比如某函数运行耗时等
window.performance.mark('mark_fully_loaded');
clearMarks
方法用于清除标记,如果不加参数,就表示清除所有标记。
window.peformance.clearMarks('mark_fully_loaded');
window.performance.clearMarks();
mark(name),measure(name, startMark, endMark),clearMarks(),clearMeasures()
- name:自定义的名称,不要和getEntries()返回的数组中其他name重复
- startMark:作为开始时间的标记名称或PerformanceTiming的一个属性
- endMark:作为结束时间的标记名称或PerformanceTiming的一个属性
创建标记:mark(name)
;
记录两个标记的时间间隔:measure(name, startMark, endMark)
;
清除指定标记:window.performance.clearMarks(name)
;
清除所有标记:window.performance.clearMarks()
;
清除指定记录间隔数据:window.performance.clearMeasures(name)
;
清除所有记录间隔数据:window.performance.clearMeasures()
;
performance.getEntries 方法
浏览器获取网页时,会对网页中每一个对象(脚本文件、样式表、图片文件等等)发出一个HTTP请求。performance.getEntries
方法以数组形式,返回这些请求的时间统计信息,有多少个请求,返回数组就会有多少个成员。
由于该方法与浏览器处理网页的过程相关,所以只能在浏览器中使用。
window.performance.getEntries()[0]
// PerformanceResourceTiming {
// responseEnd: 4121.6200000017125,
// responseStart: 4120.0690000005125,
// requestStart: 3315.355000002455,
// ...
// }
上面代码返回第一个HTTP请求(即网页的HTML源码)的时间统计信息。该信息以一个高精度时间戳的对象形式返回,每个属性的单位是微秒(microsecond),即百万分之一秒。
该对象的属性中除了包含资源加载时间还有以下五个属性。
name
:资源名称,是资源的绝对路径或调用mark方法自定义的名称startTime
:开始时间duration
:加载时间entryType
:资源类型,entryType类型不同数组中的对象结构也不同!具体见下initiatorType
:谁发起的请求,具体见下
entryType
的值:
值 | 该类型对象 | 描述 |
---|---|---|
mark | PerformanceMark | 通过mark()方法添加到数组中的对象 |
measure | PerformanceMeasure | 通过measure()方法添加到数组中的对象 |
resource | PerformanceResourceTiming | 所有资源加载时间,用处最多 |
navigation | PerformanceNavigationTiming | 现除chrome和Opera外均不支持,导航相关信息 |
frame | PerformanceFrameTiming | 现浏览器均未支持 |
server | PerformanceServerTiming | 未查到相关资料 |
initiatorType的值:
发起对象 | 值 | 描述 |
---|---|---|
a Element | link/script/img/iframe等 | 通过标签形式加载的资源,值是该节点名的小写形式 |
a CSS resourc | css | 通过css样式加载的资源,比如background的url方式加载资源 |
a XMLHttpRequest object | xmlhttprequest | 通过xhr加载的资源 |
a PerformanceNavigationTiming object | navigation | 当对象是PerformanceNavigationTiming时返回 |
/根据entryType类型返回的不同对象
PerformanceMark:{ //通过mark()方法添加的对象
entryType:"mark"
name:调用mark()方法时自定义的名字
startTime: 做标记的时间
duration:0
}
PerformanceMeasure:{ //通过measure()方法添加的对象
entryType:"measure"
name:调用measure()方法时自定义的名字
startTime: 开始量的时间
duration:标记的两个量的时间间隔
}
PerformanceResourceTiming:{ //可以用来做一个精准的进度条
entryType:"resource"
name:资源的绝对路径,即URL
startTime: 即将抓取资源的时间,
duration: responseEnd - startTime
initiatorType:略!/:傲娇脸
//其他属性请参考performance.timing
}
PerformanceNavigationTiming:{
entryType:"navigation"
name:本页路由,即地址栏看到的地址
startTime: 0
duration: loadEventEnd - startTime
initiatorType:"navigation"
//其他属性请参考performance.timing
}