Search code examples
javascriptperformancereturnnested-loopsbreak

Breaking out of nested loops: return or label/break?


I am using a JavaScript function to set a global variable. Below, I have two really dumb example functions. One uses a label to break out of the nested loops. The other uses an empty return.

My question: which is better from a performance issue? (For the sake of argument, lets say you did this a few million times.)

Using empty return

function foo() {
    for(var i = 0; i < 100; ++i) {
        for(var j = 0; j < 100; ++j) {
            if(i * j == 50) {
                myGlobal = j;
                return;
            }
        }
    }
}

Using label and break

function foo() {
    dance:
    for(var i = 0; i < 100; ++i) {
        for(var j = 0; j < 100; ++j) {
            if(i * j == 50) {
                myGlobal = j;
                break dance;
            }
        }
    }
}

I know that I will be doing nothing except finishing the function after my inner condition is met/I make my assignment.

Thanks!


Solution

  • After some testing (via Chrome console, MBP 2013, OSX 10.9, Intel i7 @ 2.8GHz, 16GB DDR3), the results are very interesting. I ran two types of tests. The first tested using return and label/break to break out of a nested loop. The second used a straight return and label/break, with nothing else in the function. The test code:

    function r() {
        for(var i = 0; i < 10; ++i) {
            for(var j = 0; j < 10; ++j) {
                if(i*j == 50) {
                    return;
                }
            }
        }
    }
    
    function b() {
        dance:
        for(var i = 0; i < 10; ++i) {
            for(var j = 0; j < 10; ++j) {
                if(i*j == 50) {
                    break dance;
                }
            }
        }
    }
    
    function r2() {
        return;
    }
    
    function b2() {
        dance:
        break dance;
    }
    
    var startTime;
    var endTime;
    
    console.log("Return test");
    startTime = Date.now();
    for(var i = 0; i < 1000000000; ++i) {
        r2();
    }
    endTime = Date.now();
    console.log(endTime - startTime);
    
    console.log("Break test");
    startTime = Date.now();
    for(var i = 0; i < 1000000000; ++i) {
        b2();
    }
    endTime = Date.now();
    console.log(endTime - startTime);
    

    When comparing breaking out of a the nested loops (functions r() and b() ), the return consistently performed significantly better. However, when using just the return or label/break in the function (functions r2() and b2() ) the label/break performed significantly faster. Test result breakdown:

    Test 1, using 10000000 iterations

    Average runtime (milliseconds) after 3 runs of using return to leave nested loops: 1215ms

    Average runtime (milliseconds) after 3 runs of using label/break to leave nested loops: 1522ms

    Test 2, using 1000000000 iterations //2 orders of magnitude more iterations

    Average runtime (milliseconds) after 3 runs of using return: 1879ms

    Average runtime (milliseconds) after 3 runs of using label/break: 1862ms

    Thus:

    For breaking nested loops, using return is ~25% faster

    For science/HPC, using label/break is ~1% faster