以下内容原文来自:
http://www.stevesouders.com/blog/2014/08/21/resource-timing-practical-tips/
http://www.stevesouders.com/blog/2014/11/25/serious-confusion-with-resource-timing/
按照自己的理解,做了整理。
一、基本定义:
1. 示例图:
2. 各个时间段的获取:
// Navigation Timing
var t = performance.timing,
pageloadtime = t.loadEventStart - t.navigationStart,
dns = t.domainLookupEnd - t.domainLookupStart,
tcp = t.connectEnd - t.connectStart,
ttfb = t.responseStart - t.navigationStart;
// Resource Timing
var r0 = performance.getEntriesByType("resource")[0],
loadtime = r0.duration,
dns = r0.domainLookupEnd - r0.domainLookupStart,
tcp = r0.connectEnd - r0.connectStart,
ttfb = r0.responseStart - r0.startTime;
3. 使用 getEntriesByType(“resource”) 而不是 getEntries().
getEntries 理论上可以有4种不同类型的返回: “resource”, “navigation”, “mark”, and “measure”。
尽管在当前浏览器的实现中,getEntriesByType(“resource”) 与 getEntries 是暂时一致的。
但为了安全起见,使用前者总是明确的。
4.注意secureConnectionStart不同取值:
1)undefined: IE浏览器下,该值不可用。见:http://msdn.microsoft.com/en-us/library/windows/desktop/aa383630(v=vs.85).aspx
2)0: HTTP协议下;
3)有值(时间戳): HTTPS协议下。(与页面本身是否采用HTTPS协议无关。)
因此,在使用该属性时候,记得先检查是否有值。例如:
var r0 = performance.getEntriesByType("resource")[0];
if ( r0.secureConnectionStart ) {
var ssl = r0.connectEnd - r0.secureConnectionStart;
}
二、跨域的问题
受同源策略影响,跨域资源获取到的时间点,通常为0.包括以下属性:
redirectStart
redirectEnd
domainLookupStart
domainLookupEnd
connectStart
connectEnd
secureConnectionStart
requestStart
responseStart
解决的方式是:
资源响应头,添加 Timing-Allow-Origin 的配置。例如:Timing-Allow-Origin:*
例如:
http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js
所以,测量时间时候,最好是加个判断:
// Resource Timing
var r0 = performance.getEntriesByType("resource")[0],
loadtime = r0.duration;
if ( r0.requestStart ) {
var dns = r0.domainLookupEnd - r0.domainLookupStart,
tcp = r0.connectEnd - r0.connectStart,
ttfb = r0.responseStart - r0.startTime;
}
if ( r0.secureConnectionStart ) {
var ssl = r0.connectEnd - r0.secureConnectionStart;
}
三、耗时为零是怎么回事?
1. 由于浏览器会缓存域名的解析,所以, domainLookupStart - domainLookupEnd 很有可能为0.
2. TCP链接是可以重用的(通常服务器和浏览器之间,可以同时保留6左右的活跃链接,具体视情况而定),
所以,connectEnd – connectStart 也有可能为0。同样的,适用于 connectEnd – secureConnectionStart = 0 的情况。
四、304响应的问题
Chrome v36还有IE10/11,当一个跨域资源(已经设置Timing-Allow-Origin)被下载后,如果重新刷新页面,由于浏览器缓存策略,这些资源有可能会返回304响应。
但是,这一次的304响应,浏览器无法正确获得缓存的Timing-Allow-Origin头部设置,从而把它认作“非法”的请求,导致出现前面提到的跨域限制,各个时间点时间为0的情况。
显然,这就导影响了测量值的准确性,得到的时延结果,有可能更高(把304视为200)或更低(把304忽略掉)。
五、最后,duration = responseEnd - redirectStart 得到的结果,有可能不是正确的。为什么?
通过浏览器测试发现,实际情况是: duration = responseEnd - redirectStart + 资源阻塞时间。
所谓 资源阻塞时间,这里指的是,由于浏览器的并发请求是有限的,通常是6~12个,在浏览器开始解析标签(如IMG),并发起请求开始,计时就已经开始了。
而在并发之外,处于等待状态的资源,得到的duration就需要比前面的资源,多出了这个阻塞(排队)的时间。从而,这个duration,就不能很好的测量浏览器到服务器直接的请求了。
示例:http://stevesouders.com/tests/rt-blocking.php 在这个页面中,会发现后面的图片加载,比前面的图片加载,要多出1~2s的时间,而这个时间,就是资源在浏览器排队阻塞的时间了。
六:可以顺便关注一下这个统计脚本:boomerang
https://github.com/lognormal/boomerang
前身是Yahoo出的,它有个插件:https://github.com/lognormal/boomerang/blob/master/plugins/restiming.js,
就基本帮我们完成一些时间点的收集功能。
附录:
测试例子:http://stevesouders.com/tests/tao.php
原文:http://www.stevesouders.com/blog/2014/08/21/resource-timing-practical-tips/
http://www.stevesouders.com/blog/2014/11/25/serious-confusion-with-resource-timing/