有没有比setTimeout和requestAnimationFrame更快的东西?

时间:2013-11-11 12:56:23

标签: javascript performance settimeout requestanimationframe

(我需要在浏览器上使用process.nextTick等效。)

我正在努力充分利用javascript性能,所以我制作了一个简单的计数器...... 在一秒钟内,我连续调用一个只向变量添加一个函数的函数。

代码:codepen.io/rafaelcastrocouto/pen/gDFxt

我使用setTimeout大约250,使用google chrome / win7中的requestAnimationFrame获得70。 我知道requestAnimationFrame与屏幕刷新率一致,所以我们怎样才能让它更快?

PS:我知道asm.js

3 个答案:

答案 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();请改用setTimeoutsetImmediate。但这并不一定是性能最好的,因为它会耗尽浏览器为其他任务所需的处理器能力。

最终,表现不仅仅是让某些东西运行最多次;它是为了让用户体验尽可能顺畅。这通常意味着对你的通话循环施加限制。

答案 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)

this blog

中所述使用postMessage()