eval的两组性能测试数据_javascript技巧

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

时间: 2024-08-04 14:20:29

eval的两组性能测试数据_javascript技巧的相关文章

使用requestAnimationFrame实现js动画性能好_javascript技巧

使用requestAnimationFrame实现js动画性能好.先给大家简单介绍下requestAnimationFrame比起setTimeout.setInterval有哪些优势? 示例一: requestAnimationFrame 比起 setTimeout.setInterval的优势主要有两点:1.requestAnimationFrame 会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,一般来说,这个频率为每秒60

JS往数组中添加项性能分析_javascript技巧

比较了4种可以向数组添加项的方法之间的性能: 使用索引器添加 复制代码 代码如下: console.time("index"); var a = []; for (var i = 0, l = times; i < l; i++) {     a[i] = i; } console.timeEnd("index"); 使用push方法 复制代码 代码如下: console.time("push"); var a = []; for (var

JS使用eval()动态创建变量的方法_javascript技巧

本文实例讲述了JS使用eval()动态创建变量的方法.分享给大家供大家参考,具体如下: 一.什么是eval()函数? eval_r()函数可计算某个字符串,并执行其中的的 JavaScript 代码. 二.如何动态定义变量? 既然eval()能够计算字符串,何不将定义变量的写法转换为字符串,然后放入eval_r()函数内进行执行,形如: var defineStr = "var number_"+i.toString(); eval_r(defineStr); 这样就定义了一个变量,你

JavaScript重定向URL参数的两种方法小结_javascript技巧

这篇文章主要介绍的是JavaScript重定向URL参数的两种方法,下面话不多说,直接看示例代码. 一.字符拼接形式 function setUri(para, val) { var strNewUrl = new String(); var strUrl = new String(); var url = window.location.href; strUrl = window.location.href; if (strUrl.indexOf("?") != -1) { strU

Js得到radiobuttonlist选中值的两种方法(推荐)_javascript技巧

如下所示: <%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false" Inherits="ajaxselect.OnmouseTitle.WebForm1" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >

探讨js字符串数组拼接的性能问题_javascript技巧

我们知道,在js中,字符串连接是性能最低的操作之一. 例如: 复制代码 代码如下: var text="Hello";  text+=" World!";  早期浏览器没有对这种运算进行优化. 由于字符串是不可变的,这意味着要创建中间字符串来存储连接的结果.频繁地在后台创建和销毁字符串导制性能异常低下. 因此,可以利用数组对象进行优化. 例如: var buffer=[],i=0; buffer[i++]="Hello"; //通过相应索引值添加

高性能Javascript笔记 数据的存储与访问性能优化_javascript技巧

局部变量也就可以理解为在函数内部定义的变量,很明显访问局部变量要比域外的变量要快,因为它位于作用域链的第一个变量对象中(关于作用域链的介绍可以阅读这篇文章).变量在作用域链的位置越深,访问所需要的时间就越长,全局变量总是最慢的,因为它们位于作用域链的最后一个变量对象. 每种数据类型的访问都需要付出点性能代价,对于直接量和局部变量基本都能消费得起,而访问数组项和对象成员则要代价高点.下图显示了不同浏览器,分别对这四种数据类型进行了200'000次操作所用的时间. 由上图可以看出,要想优化代码的性能

javascript eval和JSON之间的联系_javascript技巧

如果您想详细了解eval和JSON请参考以下链接: eval  :https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Global_Functions/Eval JSON:http://www.json.org/ eval函数的工作原理 eval函数会评估一个给定的含有JavaScript代码的字符串,并且试图去执行包含在字符串里的表达式或者一系列的合法的JavaScript语句.eval函数将把最后一个表达式或者语句所包

使用不同的方法结合/合并两个JS数组_javascript技巧

这是一篇简单的文章,关于JavaScript数组使用的一些技巧.我们将使用不同的方法结合/合并两个JS数组,以及讨论每个方法的优点/缺点. 让我们先考虑下面这情况: 复制代码 代码如下: var a = [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]; var b = [ "foo", "bar", "baz", "bam", "bun", "fun" ]; 很显然最简单的结