Performance penalty for undefined arguments

前端 未结 2 642
逝去的感伤
逝去的感伤 2021-02-08 09:41

I quite often have optional arguments in functions, but some testing is showing a huge performance hit for them in firefox and safari (70-95%). Strangely, if I pass in the liter

相关标签:
2条回答
  • 2021-02-08 10:14

    For a function like this:

    function threeArgs(x, y, z) {
      return x + y + z;
    }
    

    that's called like this:

    threeArgs(1, 2, 3);
    

    the optimizer is free to make the choice to generate no code at all. It's fairly easy for it to determine that there are no side effects, because the function simply references its parameter values and returns the result of a simple expression. Since the return value is ignored, there's no reason for the runtime to do anything at all.

    Beyond that, if the code were:

    something += threeArgs(1, 2, 3);
    

    the optimizer might decide to generate code roughly equivalent to:

    something += 6;
    

    Why? Because the call was made with numeric constants, and it can safely fold those at code generation time. It might be conservative on that, because numbers are weird, but here they're all integers so it could well do this. Even if it didn't, it could safely inline the function:

    something += 1 + 2 + 3;
    

    When there's a parameter missing, however, it may be that the optimizers bail out and generate a real function call. For such a simple function, the overhead of the function call could easily account for a large difference in performance.

    By using variables instead of constants in a test, and by actually using the return value of the function, you can "confuse" the optimizer and keep it from skipping the call or pre-computing the result, but you can't keep it from inlining. I still think that your result is interesting for that reason: it exposes the fact that (as of today anyway) those optimizers are sensitive to the way that functions are invoked.

    0 讨论(0)
  • 2021-02-08 10:35

    I think what could explain the performance difference is the way arguments are passed to a function object: via the arguments object. When not passing any arguments, JS will start by scanning the arguments object for any of the given arguments, when those are undefined, The arguments prototype chain will be scanned, all the way up to Object.prototype. If those all lack the desired property, JS will return undefined. Whereas, passing undefined explicitly, sets it as a property directly on the arguments object:

    function foo(arg)
    {
        console.log(arguments.hasOwnProperty('0'));
    }
    foo();//false'
    foo('bar');//true
    foo(undefined);//true
    

    I gather that's the reason why passing undefined explicitly tends to be faster.

    0 讨论(0)
提交回复
热议问题