@老赵 的一个微博“ 由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组测试结果:
A1 | A2 | A3 | A4 | A5 | A6 | A7 | A1 : A2 | A1 : A3 | A1 : A4 | A4 : A5 | |
Chrome | 1612ms | 8ms | 1244ms | 897ms | 7ms | 718ms | 680ms | 201.5 | 1.3 | 1.8 | 128.1 |
Firefox | 2468ms | 69ms | 732ms | 2928ms | 134ms | 5033ms | 4984ms | 35.8 | 3.4 | 0.8 | 21.9 |
IE | 1207ms | 23ms | 233ms | 1147ms | 37ms | 148ms | 224ms | 52.5 | 5.2 | 1.0 | 31.0 |
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组测试结果:
B1 | B2 | B3 | B4 | B5 | B6 | B7 | B1 : B3 | B1 : B2 | B1 : B4 | B4 : B5 | |
Chrome | 1569ms | 134ms | 1093ms | 1022ms | 173ms | 830ms | 916ms | 11.7 | 1.4 | 1.5 | 5.9 |
Firefox | 5334ms | 1017ms | 5503ms | 5280ms | 1171ms | 6797ms | 6883ms | 5.2 | 1.0 | 1.0 | 4.5 |
IE | 3933ms | 560ms | 680ms | 4118ms | 583ms | 745ms | 854ms | 7.0 | 5.8 | 1.0 | 111.3 |
结论(仅限于文中的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生成的代码效率真的很差吗?》
@Franky 的 《Eval科普》
@otakustay 的 《浅谈Eval的影响》
eval的两组性能测试数据
声明:登载此文出于传递更多信息之目的,并不意味着赞同其观点或证实其描述。
Reply on: @reply_date@
@reply_contents@