eval的两组性能测试数据 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
本文标签:eval,性能测试 @老赵 的一个微博“ 由eval生成的代码效率真的很差吗? http://t.cn/zWTUBEo 内含人身攻击,不喜勿入 。” 引发了最近对eval火爆的讨论,教主 @Franky 和 灰大 @otakustay 也给了精彩的数据分析 。 刚好之前也做过类似的测试,我也跟风凑个热闹,提供两组数据供大家参考 。 更新1: 感谢灰大 @otakustay 的指导,为排除eval()调用本身对结果的影响,增加一组新数据A3, B3 。并对旧的全部数据重测 。 更新2: 感谢莫大 @貘吃馍香 的强力拍砖,增加了1). A4, B4;A5,B5的eval覆盖后的测试数据; 2). A6,B6 eval别名;3). A7,B7 eval.call 。 测试环境: a. 机器:Intel(R) Corei7-2720 2.2Ghz (4核心8线程)、内存8Gb b. OS:Windows 7 Enterprise SP1 64-bit c. 浏览器: b.1 Google Chrome 21.0.1180.79 m b.2 Firefox 14.0.1 b.3 IE9.0.8112.16421 d. 测试方法 d.1 每个用例测试5次,耗时取最小值 。 d.2 测试过程中没有开启Firebug或Chrome Console,开启这些工具会使时间倍增,很难在有效时间内得到该用例结果 用例A1: 我们在内联函数中调用空的eval("") 复制代码 代码如下: !function() { var a = 1, b = 2, c = true; function func() { var d = 2; e = !c; eval(""); } for (var i = 0; i < 2999999; i++) { func(i, i + 1, i + 2); } }(); 用例A2: 注释掉内联函数中的eval("") 复制代码 代码如下: !function() { var a = 1, b = 2, c = true; function func() { var d = 2; e = !c; //eval(""); } for (var i = 0; i < 2999999; i++) { func(i, i + 1, i + 2); } }(); 用例A3: 为排除eval("")调用本身产生的影响,我们在外层函数中调用eval("") 复制代码 代码如下: !function() { var a = 1, b = 2, c = true; function func() { var d = 2; e = !c; } for (var i = 0; i < 2999999; i++) { eval(""); func(i, i + 1, i + 2); } }(); 用例A4: 将eval()函数覆盖成普通的空函数 复制代码 代码如下: function eval(){} !function() { var a = 1, b = 2, c = true; function func() { var d = 2; e = !c; eval(""); } for (var i = 0; i < 2999999; i++) { func(i, i + 1, i + 2); } }(); 用例A5: 同样是函数调用,不是eval而且另一个空函数f 复制代码 代码如下: function f(){} !function() { var a = 1, b = 2, c = true; function func() { var d = 2; e = !c; f(""); } for (var i = 0; i < 2999999; i++) { func(i, i + 1, i + 2); } }(); 用例A6: 将eval赋给另一个变量f,然后调用f 复制代码 代码如下: var f = eval; !function() { var a = 1, b = 2, c = true; function func() { var d = 2; e = !c; f(""); } for (var i = 0; i < 2999999; i++) { func(i, i + 1, i + 2); } }(); 用例A7: 使用eval.call的方式去调用 复制代码 代码如下: !function() { var a = 1, b = 2, c = true; function func() { var d = 2; e = !c; eval.call(null, ); } for (var i = 0; i < 2999999; i++) { func(i, i + 1, i + 2); } }(); A组测试结果:
复制代码 代码如下: for (var i = 0; i < 2999999; i++) { !function() { var a = 1, b = 2, c = true; !function () { var d = 2; e = !c; eval(""); }(); }(); } 用例B2: 复制代码 代码如下: for (var i = 0; i < 2999999; i++) { !function() { var a = 1, b = 2, c = true; !function () { var d = 2; e = !c; //eval(""); }(); }(); } 用例B3: 复制代码 代码如下: for (var i = 0; i < 2999999; i++) { !function() { var a = 1, b = 2, c = true; !function () { var d = 2; e = !c; }(); }(); eval(""); } 用例B4: 复制代码 代码如下: var eval = function(){} for (var i = 0; i < 2999999; i++) { !function() { var a = 1, b = 2, c = true; !function () { var d = 2; e = !c; eval(""); }(); }(); } 用例B5: 复制代码 代码如下: var f = function(){} for (var i = 0; i < 2999999; i++) { !function() { var a = 1, b = 2, c = true; !function () { var d = 2; e = !c; f(""); }(); }(); } 用例B6: 复制代码 代码如下: var f = eval; for (var i = 0; i < 2999999; i++) { !function() { var a = 1, b = 2, c = true; !function () { var d = 2; e = !c; f(""); }(); }(); } 用例B7: 复制代码 代码如下: for (var i = 0; i < 2999999; i++) { !function() { var a = 1, b = 2, c = true; !function () { var d = 2; e = !c; eval.call(null, ); }(); }(); } B组测试结果:
结论(仅限于文中的CASE): 1. eval本身的重复调用非常耗时,即使是空的eval(""); 2. eval对内联函数执行效率有所影响,依具体环境、代码有所不同; 3. 我们可以看到无论哪种浏览器,无论是A组还是B组,2 和 5速度较佳 。说明例中内联函数的eval无论以何种方式调用(即使eval被空函数覆盖)仍会对运行效率造成较大影响 。推断是(黑盒推断,非权威,很可能是臆测)内联函数中只要发现eval,哪怕这个eval是被覆盖的空函数,在Scope Variables中都将会把所有的外部定义的变量等内容初始化到当前的Scope中 。类似的,eval会对内联函数在运行时JS引擎的优化功能产生较大影响,降低执行效率 。 4. 说点题外话,虽然没用IE10,而是IE9,在对eval的处理上,表现非常的优异 。IE一直被开发人员诟病,但它的飞速成长也是值得肯定的,本例就是很好的一项证明 。 更详细的原因剖析下列文章描述已十分详细,不再累述 。欢迎拍砖:)尤其是莫大... @老赵 的 《由eval生成的代码效率真的很差吗?》 |