JavaScript: For循环非常缓慢,有什么方法可以加速吗?

4

我有一个从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);

很遗憾,这并没有太大的区别。

有什么我可以做来加快这个过程吗?


3
说实话,我们需要知道每个迭代中实际执行了哪些操作。根据这一点,我们可能可以建议如何改进你的算法。 - VisioN
@VisioN 不完全是这样。即使循环为空,8019000000次迭代也是过度的。 - Oriol
你的代码片段有什么意义呢?结果是显而易见的,所以@VisioN的评论非常合理。你用一个琐碎的操作进行了8019000000步,这是无法加速的... - Cedric Reichenbach
4
如果你真的需要处理80亿个项目,JavaScript可能不是我的首选语言。 - Matt R
1
totalCalc = 100*(Array(80190000).length) - KooiInc
1
这是一个真诚的问题吗? - TML
2个回答

4
把你的问题视为关于加快具有许多迭代循环的循环的一般性问题:您可以尝试使用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++;
}

1
据我所知,这可能有所帮助,但取决于解释器的实现情况。 - VisioN

3
你的示例相当简单,因此无论给出什么答案,都可能不适用于在具有如此多次迭代的循环中实际放置代码。如果你的工作可以并行完成,那么我们可以将工作分配给几个网络工作者。你可以阅读关于网络工作者的详细介绍,并学习如何使用它们,网址是:http://www.html5rocks.com/en/tutorials/workers/basics/。确定如何划分工作是一个挑战,完全取决于工作内容。由于你的示例非常简单,所以很容易将工作分配给内联的网络工作者;下面是一个函数,用于创建调用函数的异步工作者:
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);
    }
};

最后,我们可以创建一个 worker:

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

当这些部件组合在一起时,它们可以快速计算您的大量数据(当然,这取决于您的计算机有多少个CPU)。
我在jsfiddle上提供了完整的示例

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接