Search code examples
javascriptperformancescope-chain

Does minimizing the length of the scope chain improve performance?


Background

I often use the module pattern to organize my code, so that functions and constants operate on a need-to-know basis. If CONSTANT or someFunc are only used by anotherFunc, then I enclose the definition of anotherFunc in an anonymous function, so that the former two don't pollute the global scope. This helps to avoid name clashes and can also give you assurance looking at the code later of what depends on what.

This strategy does create many closures though, and I'm wondering if it might be better for performance (and more maintainable too) to pass in those dependencies explicitly. I think this has the effect of minimizing the scope chain that the function must walk to find variables.

Just to allow feedback on the module pattern itself, I've included three versions: 1) without the module pattern, 2) with it, 3) with it and scope chain minimization.

Without module pattern

var SHARED_CONSTANT;
var SOME_CONSTANT = 5;
var INNER_CONSTANT = {};
var inner = function(y) {
    return y !== {};
};
var outer = function g (x) {
    doSomething();
    $(...).load(inner);
};

With module pattern, but no scope chain minimization

var SHARED_CONSTANT;
var outer = (function() {
    var SOME_CONSTANT = 5;
    var inner = (function() {
        var INNER_CONSTANT = {};
        return function /* inner */ (y) {
            return y !== {};
        };
    }());
    return function /* outer */ (x) {
        doSomething();
        $(...).load(inner);
    };
}());

With module pattern and scope chain minimization

var SHARED_CONSTANT;
var outer = (function($, SHARED_CONSTANT) {
    var SOME_CONSTANT = 5;
    var inner = (function(SOME_CONSTANT, SHARED_CONSTANT) {
        var INNER_CONSTANT = {};
        return function /* inner */ (y) {
            return y !== {};
        };
    }(SOME_CONSTANT, SHARED_CONSTANT));
    return function /* outer */ (x) {
        doSomething();
        $(...).load(inner);
    };
}(jQuery, SHARED_CONSTANT));

Summary

Which version should have better performance (and why)? Is the difference in performance significant? (I.e. is scope chain lookup expensive?) What about memory usage? (I.e. by passing in variables, I'm essentially duplicating scope, right?)


Solution

  • These performance tests seem to confirm what I suggested. This is premature optimization.

    The tests do not show any clear favorite. For any given browser, your three snippets are close to each other, with the fastest one changing most times that I ran it. In some of the runs, the overly optimized code is even slower.

    It may be because of JIT optimizations.

    Lesson to learn: Keep your code as readable as possible and worry about optimization where you know you have bottlenecks.