最近,当我解决算法问题时,我发现了一个像这样的简单的大循环
var x = 1000000000000;
for (var i = 0; i <= x; i++) {}
可以挂起javascript引擎(在node.js,Chrome和Firefox javascript控制台上测试)。
实际上它正在运行,但速度很慢。我尝试了几个x的值,当x = 1000000时有明显的延迟。
这种表现是否与翻译语言一致?
答案 0 :(得分:2)
你可以使用某种形式的loop unrolling,将循环分解成块,例如使用Duffs device,或使用描述here的机制。
行为不仅限于解释型语言。循环将持续很长很长时间。请尝试使用c#中的for (long n = 1000000000000; n >= 0; n-=1) {}
。
最后,在(现代)浏览器中使用web workers可能是可行的。我在an example创建了另一个SO问题。
答案 1 :(得分:2)
任何语言都会很慢。在这种情况下,它特别引人注目,因为它会阻止您的用户界面。 JavaScript引擎执行单线程事件循环。您始终可以use web workers在后台执行缓慢的处理任务。
答案 2 :(得分:0)
我在MacBook Pro笔记本电脑上测试过,在现实情况下应该没问题:
如果您需要遍历超大型值,我将其拆分为较小的垃圾,并使用setTimeout
或requestAnimationFrame
将工作负载分散到不同的帧上,而不会导致任何帧丢失(框架需要约16ms的时间来完成所有工作)。
console.clear();
// options
const start = true;
const useFastTick = false; // 3ms per tick vs e.g 1s
const interval = 1; // 1: once/sec, 2: twice/sec, etc
const iterations = 1000000;
function emptyFn() {}
function argsFn(obj) {}
function emptyFns() {
for (let i = 0; i < iterations; i++) {
if (i !== undefined && i !== null) emptyFn();
}
}
function argsFns() {
for (let i = 0; i < iterations; i++) {
argsFn({a: 'hey', b: i, c: false});
}
}
function tick() {
const all0 = performance.now();
const empty0 = performance.now();
emptyFns();
const empty1 = performance.now();
const args0 = performance.now();
argsFns();
const args1 = performance.now();
const all1 = performance.now();
const all = (all1 - all0).toFixed(3);
const empty = (empty1 - empty0).toFixed(3);
const args = (args1 - args0).toFixed(3);
log(all, empty, args);
if (useFastTick) {
setTimeout(tick, 3);
} else {
setTimeout(() => requestAnimationFrame(tick), 1000 * interval);
}
}
if (start) requestAnimationFrame(tick);
// log results to console
function log(all, empty, args) {
console.group(`${all}ms`);
console.log(`Empty: ${empty}ms`);
console.log(`Arrgs: ${args}ms`);
console.groupEnd();
}