eval的两组性能测试数据


Posted in Javascript onAugust 17, 2012

@老赵 的一个微博“ 由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
用例B1:
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的影响》 

Javascript 相关文章推荐
仅用[]()+!等符号就足以实现几乎任意Javascript代码
Mar 01 Javascript
js nextSibling属性和previousSibling属性概述及使用注意
Feb 16 Javascript
jquery form表单序列化为对象的示例代码
Mar 05 Javascript
Javascript控制input输入时间格式的方法
Jan 28 Javascript
原生Js实现简易烟花爆炸效果的方法
Mar 20 Javascript
基于jquery步骤进度条源码分享
Nov 12 Javascript
JavaScript实现经典排序算法之选择排序
Dec 28 Javascript
详解Node 定时器
Feb 26 Javascript
H5+C3+JS实现五子棋游戏(AI篇)
May 28 Javascript
js实现京东秒杀倒计时功能
Jan 21 Javascript
layui 点击重置按钮, select 并没有被重置的解决方法
Sep 03 Javascript
微信小程序tabBar设置实例解析
Nov 14 Javascript
javascript五图轮播切换实用版
Aug 17 #Javascript
JS左右无缝滚动(一般方法+面向对象方法)
Aug 17 #Javascript
javascript基础知识大全 便于大家学习,也便于我自己查看
Aug 17 #Javascript
jquery插件制作 手风琴Panel效果实现
Aug 17 #Javascript
jquery插件制作 提示框插件实现代码
Aug 17 #Javascript
jquery插件制作 自增长输入框实现代码
Aug 17 #jQuery
jquery插件制作 表单验证实现代码
Aug 17 #Javascript
You might like
浅析PHP Socket技术
2013/08/02 PHP
PDO预处理语句PDOStatement对象使用总结
2014/11/20 PHP
php多重接口的实现方法
2015/06/20 PHP
php版微信支付api.mch.weixin.qq.com域名解析慢原因与解决方法
2016/10/12 PHP
safari下载文件自动加了html后缀问题
2018/11/09 PHP
浅谈php调用python文件
2019/03/29 PHP
Jquery幻灯片特效代码分享--打开页面随机选择切换方式(3)
2015/08/15 Javascript
简单讲解AngularJS的Routing路由的定义与使用
2016/03/05 Javascript
两种JavaScript的AES加密方式(可与Java相互加解密)
2016/08/02 Javascript
深入浅出讲解ES6的解构
2016/08/03 Javascript
Jquery UI实现一次拖拽多个选中的元素操作
2020/12/01 Javascript
使用ionic播放轮询广告的实现方法(必看)
2017/04/24 Javascript
Angular2使用Guard和Resolve进行验证和权限控制
2017/04/24 Javascript
利用vue和element-ui设置表格内容分页的实例
2018/03/02 Javascript
AngularJS使用$http配置对象方式与服务端交互方法
2018/08/13 Javascript
vue中组件的3种使用方式详解
2019/03/23 Javascript
微信小程序 wx.getUserInfo引导用户授权问题实例分析
2020/03/09 Javascript
python根据出生年份简单计算生肖的方法
2015/03/27 Python
python实现装饰器、描述符
2018/02/28 Python
Python3.5 Json与pickle实现数据序列化与反序列化操作示例
2019/04/29 Python
python处理大日志文件
2019/07/23 Python
django中url映射规则和服务端响应顺序的实现
2020/04/02 Python
Docker如何部署Python项目的实现详解
2020/10/26 Python
利用html5 canvas破解简单验证码及getImageData接口应用
2013/01/25 HTML / CSS
Tomcat的缺省是多少,怎么修改
2014/04/09 面试题
电子商务应届生求职信
2013/11/16 职场文书
化工专业求职信
2014/07/01 职场文书
食品安全汇报材料
2014/08/18 职场文书
党的群众路线教育实践活动自我剖析材料
2014/10/08 职场文书
2014年电话销售工作总结
2014/12/01 职场文书
2016春节慰问信范文
2015/03/25 职场文书
幼儿园小班班务总结
2015/08/03 职场文书
2016庆祝国庆67周年宣传语
2015/11/25 职场文书
小公司融资,商业计划书的8切记
2019/07/15 职场文书
详解JSON.parse和JSON.stringify用法
2022/02/18 Javascript
Redis 中使用 list,streams,pub/sub 几种方式实现消息队列的问题
2022/03/16 Redis