性能测试

如果被问到如何测试某个运算的速度,绝多数JavaScript开发者都会使用类似下面的代码:

var start = (new Date()).getTime(); // ईኁDate.now()

//需要测试的代码

var end = (new Date()).getTime();
console.log("用时:", (end - start));

相信大部分人都是这么想的吧!

但是这种方案有很多错误,这里我们能知道的只有这次运算消耗了大概这么长的时间。而它是否总是以这样的速度运行,我们基本上一无所知,你不知道JavaScript引擎这个时候有没有受到什么影响,以及其他时候这个运算会不会运行的更快,比如引擎对这种代码有特殊的优化。

这种特殊优化可能在真实的环境中使用是无法正常加速的,优化失效,那么这个运算就会比测试时跑得慢。

那么我们能知道什么呢?很遗憾,其实我们几乎一无所知,这样低信度的测试几乎无力支撑我们的任何决策,事实上这个性能测试基本是无用的,更坏的情况是,它可能给你提供了错误的信息,导致带来其他危险,不仅是对你,还有那些没有深入思考的测试人员。

此时有人会说,我们可以重复测试这段代码,然后取平均值!

简单的数学平均值绝不足以推断出它在整个应用范围内的性能,首先在重复的次数中,如果有几次运行出现异常值,比如过高和过低,都会对整个平均值产生误差。

当然,你也可以换个方式,我们不固定测试,而是在固定时间内循环运行测试,具体巴拉巴拉我也看不懂这吊书的翻译了,反正不同的浏览器引擎,它的定时器是有精度问题的,有的可能最小精度是15ms,那么就导致低于这个时间的统计结果是0ms。

综上所述,其实我们需要的是一个科学的测试,于是大佬们提供了一个库:Benchmark.js

如果你需要进行性能测试而且不懂这些门门道道的话,那么使用这个库就好了。

环境

对于特定的性能测试来说,不同的环境也是一个需要考虑的选项,针对同一段代码,在桌面端测试可能会非常快,但是在移动设备上可能就不是那么一回事了,而移动设备中,如果电量在2%的情况下,测试结果也可能是不一样的。

如果想要得到x代码比y代码快,我们需要在尽可能多的环境下进行测试,仅仅在一个环境中测试得到的结论并不意味着在所有环境都一样。

所以一个专门用于多环境测试的网站诞生了:jsPerf

但是很遗憾,这个网站在我现在去看时已经关停了,所以我们得找点新的类似网站,相信这个东西在大家上班的公司不是问题,所以我也不大费周折的找网站了。

我们需要知道环境也是测试的一环就是了。

微性能

一个有意思的话题是:++aa++谁更快?

我的观点是这个其实不重要,如果这个代码不是主要的代码,那么它微小的性能差异其实不是问题,因为优化它带来的收益非常非常小。

有时候这种优化可能是针对JavaScript引擎的专门优化,但是并不是所有的JavaScript引擎都符合规范,所以可能你针对a引擎优化的是很快,换了另一个反倒是次优的。

举个例子:

以前字符的拼接业界推荐使用数组,将字符存放在数组中,最后调用join("")方法,因为这样的方式比直接使用+拼接要快。

造成这样的原因涉及到字符串值在内存中如何存储和管理这样的细节。非常微妙!

但是随着时间推移,JavaScript引擎改变了内存管理字符串的方法,特别是+连接操作进行了优化。但是并没有因此故意降低join的性能,而是花了更多精力提高+的性能是使用率(钦定的拼接方式)。

此时我们再回过头来看,当+成为了新的红人,那些通过数组join的方式就成了次优的了。

再有一点我们需要知道,你的hack代码可能会比浏览器的版本存活的时间更久,你看看现在浏览器的版本更新,少说每个月都会有一次,所以如果发现了一个性能问题,第一该考虑的是提交bug给浏览器,而不是直接去写绕过性能bug的代码。

分类: 你不知道的JavaScript 标签: 测试性能微性能hack

评论

暂无评论数据

暂无评论数据

目录