Question

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!

Était-ce utile?

La 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

Autres conseils

I personally don't see anything wrong with empty return statements to abort execution early for a function that doesn't return anything normally. It's certainly cleaner than a label, and it's more language-agnostic too. A lot of languages don't support labeled for loops like whatever language your example is in, so the empty return statement will be simpler to understand for people coming from other languages lacking that feature.

Both have the same performance; the former arguably is more readable. However, the latter makes it easier to modify the function should you need to add more instructions in the future after the loops.

UPDATE:

Good info here: Why JavaScript functions always return a value?, first answer says: 'Thus, return and function-executed-to-its-end semantics match.' So even if you use break, at the end of the execution it will return the same as if you use return

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top