Daniela
Daniela

Reputation: 179

Javascript: For loop extremely slow, any way to speed it up?

I have a for-loop from 0 to 8,019,000,000 that is extremely slow.

var totalCalcs = 0;
for (var i = 0; i < 8019000000; i++)
    totalCalcs++;
window.alert(totalCalcs);

in chrome this takes between 30-60secs.

I also already tried variations like:

var totalCalcs = 0;
for (var i = 8019000000; i--; )
    totalCalcs++;
window.alert(totalCalcs);

Didn't do too much difference unfortunately.

Is there anything I can do to speed this up?

Upvotes: 4

Views: 8149

Answers (2)

Andrew Vermie
Andrew Vermie

Reputation: 633

Your example is rather trivial, and any answer may not be suitable for whatever code you're actually putting inside of a loop with that many iterations.

If your work can be done in parallel, then we can divide the work between several web workers.
You can read a nice introduction to web workers, and learn how to use them, here: http://www.html5rocks.com/en/tutorials/workers/basics/

Figuring out how to divide the work is a challenge that depends entirely on what that work is. Because your example is so small, it's easy to divide the work among inline web workers; here is a function to create a worker that will invoke a function asynchronously:

var makeWorker = function (fn, args, callback) {
    var fnString = 'self.addEventListener("message", function (e) {self.postMessage((' + fn.toString() + ').apply(this, e.data))});',
        blob = new Blob([fnString], { type: 'text/javascript' }),
        url = URL.createObjectURL(blob),
        worker = new Worker(url);

    worker.postMessage(args);
    worker.addEventListener('message', function (e) {
        URL.revokeObjectURL(url);
        callback(e.data);
    });

    return worker;
};

The work that we want done is adding numbers, so here is a function to do that:

var calculateSubTotal = function (count) {
    var sum = 0;
    for (var i = 0; i < count; ++i) {
        sum++;
    }
    return sum;
};

And when a worker finishes, we want to add his sum to the total AND tell us the result when all workers are finished, so here is our callback:

var total = 0, count = 0, numWorkers = 1,
    workerFinished = function (subTotal) {
    total += subTotal;
    count++;

    if (count == numWorkers) {
        console.log(total);
    }
};

And finally we can create a worker:

makeWorker(calculateSubTotal, [10], workerFinished); // logs `10` to console

When put together, these pieces can calculate your large sum quickly (depending on how many CPUs your computer has, of course).

I have a complete example on jsfiddle.

Upvotes: 3

KooiInc
KooiInc

Reputation: 122906

Treating your question as a more generic question about speeding up loops with many iterations: you could try Duff's device.

In a test using nodejs the following code decreased the loop time from 108 seconds for your second loop (i--) to 27 seconds

var testVal = 0, iterations = 8019000000;
var n = iterations % 8;
while (n--) {
 testVal++;
}
n = parseInt(iterations / 8);
while (n--) {
 testVal++;
 testVal++;
 testVal++;
 testVal++;
 testVal++;
 testVal++;
 testVal++;
 testVal++;
}

Upvotes: 4

Related Questions