eval的两组性能测试数据

引发了最近对eval火爆的讨论,刚好之前也做过类似的测试,我也跟风凑个热闹,提供两组数据供大家参考。 

测试环境:

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一直被开发人员诟病,但它的飞速成长也是值得肯定的,本例就是很好的一项证明。 

作者:Bosn
微博:@Bosn
主页:bosn.me
简介:工程师、音乐人
原文地址:https://www.cnblogs.com/bosnma/p/2643268.html