fredshare / blog

护卫银河
https://fredshare.github.com/blog/
112 stars 23 forks source link

window.performance 详解 #5

Open fredshare opened 10 years ago

fredshare commented 10 years ago

window.performance详解

performance的作用

浏览器暴露给js的一个接口,可以通过这个接口查看用户访问网站的连接建立时间、dns时间等信息。使用该api时需要在页面完全加载完成之后才能使用,最简单的办法是在window.onload事件中读取各种数据,因为很多值必须在页面完全加载之后才能得出。

浏览器支持情况

IE9和chrome6以上的版本都支持:

img 可以看到api的接口定义如下:

memory:浏览器内存情况

  1. jsHeapSizeLimit
  2. totalJSHeapSize
  3. usedJSHeapSize 注:usedJSHeapSize表示所有被使用的js堆栈内存;totalJSHeapSize表示当前js堆栈内存总大小,这表示usedJSHeapSize不能大于totalJSHeapSize,如果大于,有可能出现了内存泄漏

    navigation :网页导航相关

  4. redirectCount:重定向属性 一个只读属性,返回当前页面是几次重定向才过来的。但是这个接口有同源策略限制,即仅能检测同源的重定向。
  5. type 返回值应该是0,1,2 中的一个。分别对应三个枚举值:
    0 : TYPE_NAVIGATE (用户通过常规导航方式访问页面,比如点一个链接,或者一般的get方式)
    1 : TYPE_RELOAD (用户通过刷新,包括JS调用刷新接口等方式访问页面)
    2 : TYPE_BACK_FORWARD (用户通过后退按钮访问本页面)

    timing :测速相关

img

navigationStart:准备加载新页面的起始时间 redirectStart:如果发生了HTTP重定向,并且从导航开始,中间的每次重定向,都和当前文档同域的话,就返回开始重定向的timing.fetchStart的值。其他情况,则返回0 redirectEnd:如果发生了HTTP重定向,并且从导航开始,中间的每次重定向,都和当前文档同域的话,就返回最后一次重定向,接收到最后一个字节数据后的那个时间.其他情况则返回0 fetchStart:如果一个新的资源获取被发起,则 fetchStart必须返回用户代理开始检查其相关缓存的那个时间,其他情况则返回开始获取该资源的时间 domainLookupStart:返回用户代理对当前文档所属域进行DNS查询开始的时间。如果此请求没有DNS查询过程,如长连接,资源cache,甚至是本地资源等。 那么就返回 fetchStart的值 domainLookupEnd:返回用户代理对结束对当前文档所属域进行DNS查询的时间。如果此请求没有DNS查询过程,如长连接,资源cache,甚至是本地资源等。那么就返回 fetchStart的值 connectStart:返回用户代理向服务器服务器请求文档,开始建立连接的那个时间,如果此连接是一个长连接,又或者直接从缓存中获取资源(即没有与服务器建立连接)。则返回domainLookupEnd的值 (secureConnectionStart):可选特性。用户代理如果没有对应的东东,就要把这个设置为undefined。如果有这个东东,并且是HTTPS协议,那么就要返回开始SSL握手的那个时间。 如果不是HTTPS, 那么就返回0 connectEnd:返回用户代理向服务器服务器请求文档,建立连接成功后的那个时间,如果此连接是一个长连接,又或者直接从缓存中获取资源(即没有与服务器建立连接)。则返回domainLookupEnd的值 requestStart:返回从服务器、缓存、本地资源等,开始请求文档的时间 responseStart:返回用户代理从服务器、缓存、本地资源中,接收到第一个字节数据的时间 responseEnd:返回用户代理接收到最后一个字符的时间,和当前连接被关闭的时间中,更早的那个。同样,文档可能来自服务器、缓存、或本地资源 domLoading:返回用户代理把其文档的 "current document readiness" 设置为 "loading"的时候 domInteractive:返回用户代理把其文档的 "current document readiness" 设置为 "interactive"的时候. domContentLoadedEventStart:返回文档发生 DOMContentLoaded事件的时间 domContentLoadedEventEnd:文档的DOMContentLoaded 事件的结束时间 domComplete:返回用户代理把其文档的 "current document readiness" 设置为 "complete"的时候 loadEventStart:文档触发load事件的时间。如果load事件没有触发,那么该接口就返回0 loadEventEnd:文档触发load事件结束后的时间。如果load事件没有触发,那么该接口就返回0

组合值的意义

DNS查询耗时 :domainLookupEnd - domainLookupStart TCP链接耗时 :connectEnd - connectStart request请求耗时 :responseEnd - responseStart 解析dom树耗时 : domComplete - domInteractive 白屏时间 :responseStart - navigationStart domready时间 :domContentLoadedEventEnd - navigationStart onload时间 :loadEventEnd - navigationStart

performance.getEntries 资源测速

img 比如图中type为img的图片整个加载时间为duration ms。 可以通过这个接口统计整个页面有多少img、css、js以及对应的下载时间等信息。

常用统计方法

performance 测速上报

     /**
 * 上报Performance timing数据;
 * 如果某个时间点花费时间为0,则此时间点数据不上报。
 * @param {String}
 *            f1 flag1简写,测速系统中的业务ID,譬如校友业务为164
 * @param {String}
 *            f2 flag2简写,测速的站点ID
 * @param {String}
 *            f3_ie flag3简写,测速的页面ID
 *(因为使用过程中我们发现IE9的某些数据存在异常,
 * 如果IE9和chrome合并统计,会影响分析结果,所以这里建议分开统计)
 * @param {String}
 *            f3_c flag3简写,测速的页面ID
 * (如果为空,则IE9和chrome合并统计)
 */
function setTimingRpt(f1, f2, f3_ie, f3_c){     
    var _t, _p = (window.webkitPerformance ? window.webkitPerformance : window.msPerformance), _ta = ["navigationStart","unloadEventStart","unloadEventEnd","redirectStart","redirectEnd","fetchStart","domainLookupStart","domainLookupEnd","connectStart","connectEnd","requestStart",/*10*/"responseStart","responseEnd","domLoading","domInteractive","domContentLoadedEventStart","domContentLoadedEventEnd","domComplete","loadEventStart","loadEventEnd"], _da = [], _t0, _tmp, f3 = f3_ie;  
    _p = (_p ? _p : window.performance);        
    if (_p && (_t = _p.timing)) {       
        if (!_t.domContentLoadedEventStart) {
            _ta.splice(15, 2, 'domContentLoaded', 'domContentLoaded');
        } else {
            if (f3_c) {
                f3 = f3_c;
            }
        }           
        _t0 = _t[_ta[0]];
        for (var i = 1, l = _ta.length; i < l; i++) {
            _tmp = _t[_ta[i]];
            _tmp = (_tmp ? (_tmp - _t0) : 0);
            if (_tmp > 0) {
                _da.push( i + '=' + _tmp);
            }
        }           
        if (window.d0) {//统计页面初始化时的d0时间
            _da.push('30=' + (window.d0 - _t0));
        }           
        var url = 'http://www.report.com?flag1=' + f1 + '&flag2=' + f2 + '&flag3=' + f3 + '&' + _da.join('&');      
        var _img = new Image();
        setTimeout(function(){
            _img.src = url;
        }, 10);
    }       
};
//注意!需要在onload事件后进行计算上报。
window.onload = function(){
    setTimingRpt(7839, 7, 3);//活动页面
};

performance chrome可视化插件

performance chrome可视化插件

未完待续!! 参考:

HTML5 performance API 草案 Resource Timing

hehongwei44 commented 9 years ago

相当不错

fredshare commented 9 years ago

@hehongwei44 多谢支持~~

hehongwei44 commented 9 years ago

用在实际项目中了嘛 稳定性怎么样

fredshare commented 9 years ago

@hehongwei44 实际测速就是用performance接口的,移动端支持度在40~60%左右。

hehongwei44 commented 9 years ago

我也是用performance对像来上报的,不过没有你封装的优雅

hehongwei44 commented 9 years ago

还请教你一个问题,不支持performance对象的浏览器 怎么做上报的。腾讯是怎么做的呢?@fredshare

fredshare commented 9 years ago

不支持performance的情况下,我们做了domready、onload、白屏时间等的统计,通过埋点的方式进行计算统计,比如domready,head最前面埋一个点,html尾部卖一个点,两个之间的差值大约等于domready时间;onload就是用DOMContentLoaded触发的时候打点等。 我记得还有多普勒测速,这个是在performance标准出来之前很多公司有使用到的方案。

hehongwei44 commented 9 years ago

有写地方没太明白,setTimingRpt中的f1,f2,f3_ie,f3_c 具体指的是什么?我只是把_da上传服务器接口,你的那些参数是不是对我作用不大?

hehongwei44 commented 9 years ago

还有个问题就是,你的_da参数得到的值都是与navigationStart的差值,比如我要得到“解析dom树耗时”,但是_da没有提供,你们是不是后台对其进行了处理。

fredshare commented 9 years ago

image 哦,这个涉及到上报系统的数据结构定义,可能一个业务下有多个站点,每个站点下有不少页面,需要针对每一个业务、站点、页面分别申请不一样的id来区别

fredshare commented 9 years ago

@hehongwei44 这个demo中的函数是一个标准的上报performance接口的函数 如果需要上报比如dom树解析耗时,你需要前端算出dom树解析,然后上报。计算方法: image

hehongwei44 commented 9 years ago

哦 我了解了,不过你上传页面的URL应该也可以做到区分是哪个页面的上报吧,只是你们自己对齐封装了吧。

fredshare commented 9 years ago

@hehongwei44 是的,前端封装好了,后台来区分比较麻烦,需要维护一大堆map对应表

hehongwei44 commented 9 years ago

哦 我了解了,因为你我的业务场景不一样,你的函数看样子,我不能直接拿上就用。自己还得在你的代码上做一层封装。

hehongwei44 commented 9 years ago

if (!_t.domContentLoadedEventStart) { _ta.splice(15, 2, 'domContentLoaded', 'domContentLoaded'); } else { if (f3_c) { f3 = f3_c; } } 你这段代码的意图是什么?

fredshare commented 9 years ago

@hehongwei44 image

hehongwei44 commented 9 years ago

能说说异常出现的原因嘛

fredshare commented 9 years ago

@hehongwei44 你可以看看这个http://www.cnblogs.com/_franky/archive/2011/11/07/2238980.html 上面有详细的解释

ywang1724 commented 9 years ago

关于其中几项值的计算方法有些疑问,麻烦楼主解答 1、request请求耗时 :responseEnd - responseStart 是否应该为responseEnd - requestStart? 2、白屏时间 :responseStart - navigationStart responseStart 是开始接收响应的时间,白屏时间是指页面开始出现内容的时间,这两个时间是否是一样的?

zlzdp commented 9 years ago

mark

chua1989 commented 8 years ago

@ywang1724 所以说白屏时间计算的不对,白屏时间=开始渲染时间(首字节时间+HTML下载完成时间)+头部资源加载时间;对应的应该是白屏时间=domLoading - navigationStart +头部资源加载时间;头部资源加载时间还是要自己算

zhujun24 commented 8 years ago

loadEventEnd:文档触发 load事件结束后 的时间。如果load事件没有触发,那么该接口就返回0。所以在onload 里计算这个是不是会出问题?

hellozhangran commented 7 years ago

request请求耗时 :responseEnd - responseStart 这一条我不太理解,尤其是responseEnd这个时间点。 responseEnd指的是服务器返回最后一个字节的时间!那这最后一个字节指的是什么呢? 如果请求一个html页面,那最后一个字节指的是html页面返回完毕?还是里面的js、css返回完毕。。。如果是的话,responseEnd - responseStart 应该是下载时间了吧,怎么只是请求时间呢??

zqs-zjj-1208 commented 7 years ago

大神 ,你好。敢问如何测试监控移动端设备呢?没写过js,不知道怎么弄,望百忙之中指点一二,多谢!!!

reaperme commented 6 years ago

你这里的白屏时间计算是错误的,没有包括头部资源加载的时间

fredshare commented 6 years ago

@reaperme ,在responseStart开始的时候,页面就开始渲染了。

fredshare commented 6 years ago

@zqs-zjj-1208 移动端监控是一样的,移动端也有performance接口

fredshare commented 6 years ago

@hellozhangran 这里的请求耗时指的是从发起请求到请求结束的时间

junbinxu commented 5 years ago

您好,请问怎么获取每个资源的waiting time ?

moozeeli commented 4 years ago

图片看不到了,是我网络的问题吗?