最近需要针对现有的一些线上产品,进行优化工作。首先得对这些产品的性能做一个统计,找出目前问题最严重的,优先进行改进。前面我都是通过在自己本地电脑上测试,利用诸如YSLOW、PageSpeed之类的工具来检测性能。但是通过这些方法,得到的结果都是比较理想的,没有并发因素,网络也因为是内网环境,非常给力,每个产品体现出来都还挺快。因此最终还是决定搜集用户端真实的页面加载耗时来作为参考标准。
在考虑如何搜集用户端数据的过程中,一开始,是准备在页面上通过JS进行埋点,类似这种方式:
<script> T = T || {}; T.beforeHead = new Date().getTime(); </script>
在页面的不同点记录时间戳,最终在load完成后,统计发送到服务端进行分析。但是搜索了网上的资料,发现这种形式存在一些弊端:
1.这会驱使JS引擎比平时更早的加载
2.让HTML和JS的解析器频繁更换上下文
3.嵌入的JS代码片段会阻塞剩余资源的加载
4.不能捕获到网络延迟的时间消耗(服务器到客户端的这一个时间消耗)
5.new Date().getTime()在各个浏览器中,平均耗时为7.5ms,你的应用越简单,那么这个时间消耗对你性能测试结果的影响就会越大
6.这种埋点方式也增加了性能测试的工作量,因为你需要花费额外的时间来维护这些JS片段
由于需要测试的产品有多个,理想的情况是自己写一个脚本,然后每个产品页面引入一下,自动完成这部分工作。有鉴于上述几个因素,又经过网上的一些搜索,发现了雅虎前端编写的一个性能统计工具:BOOMERANG,利用这个工具可以自动的完成页面加载时间的统计。它提供的统计项比较多,由于我们需要用到的功能只有前端整个页面的加载耗时,因此我从其源码中把该功能摘录了出来,实现的原理是利用W3C提供的Navigation Timing API来获取打开页面时的时间戳,然后当页面load完成后,通过new Date().getTime()获取时间戳,两者相减极为页面加载的完整时间。注意目前仅IE9、Chrome6+浏览器实现了该API。下面是获取页面打开时间戳的代码:
var _initStartTime = function () { var performance, startTime = false; performance = window.performance || window.msPerformance || window.webkitPerformance || window.mozPerformance; if (performance && performance.timing && performance.timing.navigationStart) { startTime = performance.timing.navigationStart; // Chrome Browser } else if(window.chrome && window.chrome.csi && window.chrome.csi().startE) { startTime = w.chrome.csi().startE; // The Google Toolbar exposes navigation start time similar to old versions of chrome // This would work for any browser that has the google toolbar installed } else if(window.gtbExternal && window.gtbExternal.startE()) { startTime = window.gtbExternal.startE(); } // 解决火狐7.8的bug if (navigator.userAgent.match(/Firefox\/[78]\./)) { this.navigationStart = performance.timing.unloadEventStart || performance.timing.fetchStart || undefined; } return startTime; };
通过这种方式,就可以得到较为准确的耗时数据了。
在内网环境我自己电脑上,测试产品C的页面耗时均值约为1秒;而通过上面的方法,统计线上用户端的时间消耗均值,约为4秒。两者差异相当大,可见我们的产品优化潜力还是非常大的。