(我需要在浏览器上使用process.nextTick等效。)
我正在努力充分利用javascript性能,所以我制作了一个简单的计数器...... 在一秒钟内,我连续调用一个只向变量添加一个函数的函数。
代码:codepen.io/rafaelcastrocouto/pen/gDFxt
我使用setTimeout大约250,使用google chrome / win7中的requestAnimationFrame获得70。 我知道requestAnimationFrame与屏幕刷新率一致,所以我们怎样才能让它更快?
PS:我知道asm.js
答案 0 :(得分:27)
嗯,有setImmediate()
可以立即运行代码,也就是说你期望得到setTimeout(0)
。
不同之处在于setTimeout(0)
实际上并不立即运行; setTimeout
被“钳制”到最短等待时间(4ms),这就是为什么你的测试程序中只有250的计数。 setImmediate()
确实立即运行,因此使用它可以使您的计数器测试值高出几个数量级。
但是,您可能需要检查setImmediate
的浏览器支持 - 它在所有浏览器中都不可用。 (当然,你可以使用setTimeout(0)
作为后退,但是你会回到它施加的最短等待时间。)
postMessage()
也是一个选项,并且可以获得相同的结果,虽然它是一个更复杂的API,因为它的目的是为了做更多的事情而不仅仅是一个简单的调用循环。此外,在使用它时还需要考虑其他因素(有关更多信息,请参阅链接的MDN文章)。
MDN网站还提到a polyfill library for setImmediate
使用postMessage
和其他技术将setImmediate
添加到尚不支持它的浏览器中。
使用requestAnimationFrame()
,您的测试程序应该得到60,因为这是每秒的标准帧数。如果你得到的不止于此,那么你的程序可能会运行超过一秒钟。
你的计数测试中你永远不会得到很高的数字,因为它只会每秒发射60次(如果硬件刷新帧速率因某种原因而降低,则更少),但如果你的任务涉及更新显示然后就是你所需要的,这样你就可以使用requestAnimationFrame()
来限制它被调用的次数,从而为你的程序中的其他任务腾出资源。
这就是requestAnimationFrame()
存在的原因。如果你关心的只是让代码尽可能频繁地运行,那就不要使用requestAnimationFrame()
;请改用setTimeout
或setImmediate
。但这并不一定是性能最好的,因为它会耗尽浏览器为其他任务所需的处理器能力。
最终,表现不仅仅是让某些东西运行最多次;它是为了让用户体验尽可能顺畅。这通常意味着对你的通话循环施加限制。
答案 1 :(得分:7)
仍然是异步的最短可能延迟来自MutationObserver
,但它很短,如果你继续调用它,UI将永远不会有机会更新。
所以诀窍是使用MutationObserver
来增加值,偶尔使用requestAnimationFrame
来更新UI,但这是不允许的。
多么愚蠢的比赛。
请参阅http://jsfiddle.net/6TZ9J/1/
var div = document.createElement("div");
var count = 0;
var cur = true;
var now = Date.now();
var observer = new MutationObserver(function () {
count++;
if (Date.now() - now > 1000) {
document.getElementById("count").textContent = count;
} else {
change();
}
});
observer.observe(div, {
attributes: true,
childList: true,
characterData: true
});
function change() {
cur = !cur;
div.setAttribute("class", cur);
}
change();
答案 2 :(得分:1)
postMessage()