Search code examples
javascriptfirefoxspidermonkey

Why does the function constructor is less performant in SpiderMonkey than a function definition?


By this jsPerf, the construct

var fn2 = new Function('return 1 + 2;');

yields a function which takes more time to be called than the function defined by:

var fn1 = function() {
    return 1 + 2;
};

Why is this so? Apparently the overhead lies only in calling the function, not in running its body (so the body itself is apparently optimized). This has be shown by other tests on jsperf.

Using the function constructor makes sense when dynamically generating code (i.e. using SpiderMonkey as a Javascript JIT compiler) so it is bad to see that there is a performance penalty. (Using eval instead of the function constructor is faster but eval makes the whole scope accessible to the function which is not what I want.)

It is interesting to see that this version

var fn4 = new Function('return function () { return 1 + 2; }')();

returns a function as fast as fn1 from above. However, doesn't this blow-up the inner function as it still carries around a handle to the empty scope of the outer function? (Assume that I have to create many of these functions so that these micro-optimizations could make sense.)


Solution

  • Looks like there was a bug in the SpiderMonkey JIT where it sometimes failed to properly inline functions created with new Function. Note that in this testcase once all the functions are inlined all that's really being timed is the empty loop, since the function bodies are constant and get loop-hoisted...

    In any case, https://bugzilla.mozilla.org/show_bug.cgi?id=958797 tracks the fix for the inlining issue.