Javascript:For loop非常慢,有什么方法可以加快速度吗?

时间:2014-05-07 15:13:51

标签: javascript performance loops for-loop

我有一个从0到8,019,000,000的for循环非常慢。

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

在chrome中需要30-60秒。

我也尝试了类似的变体:

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

不幸的是,没有做太大的差异。

我有什么办法可以加快速度吗?

2 个答案:

答案 0 :(得分:3)

您的示例相当简单,任何答案可能都不适合您实际放入具有多次迭代的循环内的任何代码。

如果您的工作可以并行完成,那么我们可以将工作分成几个网络工作人员。
您可以阅读对Web工作者的精彩介绍,并在此处学习如何使用它们: http://www.html5rocks.com/en/tutorials/workers/basics/

弄清楚如何划分工作是一项挑战,完全取决于工作的内容。因为你的例子很小,所以很容易在内联网络工作者之间划分工作;这是一个创建将异步调用函数的worker的函数:

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;
};

我们想要完成的工作是添加数字,所以这里有一个功能:

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

当一个工人完成时,我们想要将他的总和加到总数中并告诉我们所有工人完成后的结果,所以这是我们的回调:

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

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

最后我们可以创建一个工人:

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

当放在一起时,这些部分可以快速计算您的大笔金额(当然,取决于您的计算机有多少CPU)。

我有complete example on jsfiddle

答案 1 :(得分:2)

将您的问题视为一个关于通过多次迭代加速循环的更通用的问题:您可以尝试Duff's device

在使用nodejs的测试中,以下代码将第二个循环(i--)的循环时间从108秒减少到27秒

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++;
}