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 相关文章推荐
jquery常用技巧及常用方法列表集合
Apr 06 Javascript
登陆成功后自动计算秒数执行跳转
Jan 23 Javascript
JS小游戏之仙剑翻牌源码详解
Sep 25 Javascript
jquery实现隐藏在左侧的弹性弹出菜单效果
Sep 18 Javascript
js老生常谈之this,constructor ,prototype全面解析
Apr 05 Javascript
jQuery搜索框效果实现代码(百度关键词联想)
Feb 25 Javascript
jQuery实现的分页功能示例
Jan 22 Javascript
jQuery插件FusionWidgets实现的Cylinder图效果示例【附demo源码】
Mar 23 jQuery
巧用weui.topTips验证数据的实例
Apr 17 Javascript
Vue.js 实现微信公众号菜单编辑器功能(一)
May 08 Javascript
vue中v-for循环给标签属性赋值的方法
Oct 18 Javascript
js面向对象编程OOP及函数式编程FP区别
Jul 07 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远程连接MYSQL数据库非常慢的解决方法
2008/07/05 PHP
PHP下操作Linux消息队列完成进程间通信的方法
2010/07/24 PHP
Yii2框架使用计划任务的方法
2016/05/25 PHP
PHP函数rtrim()使用中的怪异现象分析
2017/02/24 PHP
PHP编程文件处理类SplFileObject和SplFileInfo用法实例分析
2017/07/22 PHP
6个常见的 PHP 安全性攻击实例和阻止方法
2020/12/16 PHP
js获取当前select 元素值的代码
2010/04/19 Javascript
基于jquery的inputlimiter 实现字数限制功能
2010/05/30 Javascript
jQuery学习笔记 操作jQuery对象 文档处理
2012/09/19 Javascript
Js日期选择器并自动加入到输入框中示例代码
2013/08/02 Javascript
js和php如何获取当前url的内容
2013/09/22 Javascript
一个支付页面DEMO附截图
2014/07/22 Javascript
jQuery中:has选择器用法实例
2014/12/30 Javascript
Node.js的基本知识简单汇总
2016/09/19 Javascript
Angular ng-class详解及实例代码
2016/09/19 Javascript
基于jQuery插件jqzoom实现的图片放大镜效果示例
2017/01/23 Javascript
详谈jQuery.load()和Jsp的include的区别
2017/04/12 jQuery
vue实现多条件和模糊搜索功能
2019/05/28 Javascript
js简单的分页器插件代码实例
2019/09/11 Javascript
jquery实现加载更多&quot;转圈圈&quot;效果(示例代码)
2020/11/09 jQuery
Python Paramiko模块的使用实际案例
2018/02/01 Python
Django框架文件上传与自定义图片上传路径、上传文件名操作分析
2019/05/10 Python
一行Python代码过滤标点符号等特殊字符
2019/08/12 Python
jupyter notebook 添加kernel permission denied的操作
2020/04/21 Python
Python + opencv对拍照得到的图片进行背景去除的实现方法
2020/11/18 Python
python反扒机制的5种解决方法
2021/02/06 Python
HTML5 通信API 跨域门槛将不再高、数据推送也不再是梦
2013/04/25 HTML / CSS
DHC美国官网:日本通信销售第一的化妆品品牌
2017/11/12 全球购物
idealfit英国:世界领先的女性健身用品和运动衣物品牌
2017/11/25 全球购物
怀旧收藏品和经典纪念品:Betty’s Attic
2018/08/29 全球购物
Shop Apotheke瑞士:您的健康与美容网上商店
2019/10/09 全球购物
应聘教师推荐信
2013/10/31 职场文书
奠基仪式主持词
2014/03/20 职场文书
新员工辞职信范文
2015/05/12 职场文书
2019年教师节:送给所有老师的祝福语
2019/09/05 职场文书
python周期任务调度工具Schedule使用详解
2021/11/23 Python