空尝试如何影响性能?

时间:2015-11-19 02:44:47

标签: javascript performance google-chrome try-catch performance-testing

我知道空try... catch不是好的程序练习。但是,我想知道空try... catch影响JavaScript性能的原因?

以下代码摘要:

function test() {
    var start = new Date();

    for (var i = 0; i < 100000000; i++){
        var r = i % 2;
    }

    console.log(new Date() - start);

    try {

    } catch (ex) {

    }
}

709

下的运行时结果为Chrome

但是,没有空try... catch

function test3() {
    var start = new Date();

    for (var i = 0; i < 100000000; i++){
        var r = i % 2;
    }

    console.log(new Date() - start);

}

运行时结果为132

正常情况下,

function test1() {
    var start = new Date();
    try {

        for (var i = 0; i < 100000000; i++){
            var r = i % 2;
        }

        console.log(new Date() - start);

    } catch (ex) {

    }
}

结果为792

修改

如果我把这个空try catch放到另一个函数

function test4() {
    var start = new Date();

    for (var i = 0; i < 100000000; i++){
        var r = i % 2;
    }

    console.log(new Date() - start);

    wrap();
}    

function wrap() {
    try {

    } catch (ex) {

    }
}

结果为130,因此我认为try catchfunction scope。我是对的还是错过了什么?

2 个答案:

答案 0 :(得分:4)

这非常依赖于JIT的实现。它无法在一般背景下回答。

但是,您的基准测试很可能会给您带来误导性的结果,特别是在这里:

for (var i = 0; i < 100000000; i++){
    var r = i % 2;
}

即使是玩具编译器也可以将其优化为NOOP,并且无需额外的努力就可以消除整个循环。这是因为这不会产生任何相关的副作用(“相关”,因为它对程序的输出没有影响,或者从较低级别的角度来看,它对将要在其他地方访问的内存没有影响)。

因此,对于任何不错的优化器,你基本上都计算了什么都不做的成本(优化器会在快速意识到它没有影响用户输出的副作用之后跳过你实际尝试进行基准测试的工作)。

由于优化程序可以做什么,微基准测试是众所周知的误导。如果你不小心确保在不影响用户输出的情况下不能跳过工作,他们就会跳过你想要的时间。

如果要构建有意义的基准测试,通常希望至少以某种方式对计算进行聚合或求和,以使其成为用户输出。例如,您可以尝试将每次迭代中r的结果求和为一些外部变量,其值在计算结束时打印出来。这可能会使优化器跳过一堆计算成为指数级的难度,此时你可能会很快开始看到有或没有空try/catch块的更多可比时间,以及你是否放了一个{ {1}}围绕循环。

现在,基于你所看到的,并且这进入了猜想领域,似乎引入空的try / catch块阻止你的特定JIT能够跳过在该循环中完成的工作。编译器可以在每个函数级别粗略地处理异常处理,简化为一种简单的处理,“此函数是否需要异常处理?是/否?如果是,请避免某些优化对于整个功能。“

这纯粹是一种有根据的猜测 - 唯一可以确定的方法是了解JIT的内部结构或查看生成的装配体。

答案 1 :(得分:0)

我在chrome和firefox中进行了两项测试:

let array = [];

function test1(){
  try{
    console.log('begin test 1..');

    let startTime = new Date();
    for(let i = 0; i < 10000000;i++){
      array.push('');
    }
    console.log('result: ', new Date() - startTime);
  }
  catch(err){
    console.error(err);
  }
}

function test2(){
    console.log('begin test 2..');

    let startTime = new Date();
    for(let i = 0; i < 10000000;i++){
      array.push('');
    }
    console.log('result: ', new Date() - startTime);
}

array.length = 0;
test1();
array.length = 0;
test2();

Chrome的结果是:测试1中为378ms,测试2中为368ms(差异为102%)。
Firefox的结果是:测试1中为1262ms,测试2中为1223ms(差异为103%)

我已经测试了其他一些操作,例如函数调用,除法等,但是结果保持稳定。

目前,try / catch不会对性能产生太大影响