15

(我需要浏览器上的 process.nextTick 等效项。)

我试图充分利用 javascript 的性能,所以我做了一个简单的计数器......在一秒钟内,我连续调用一个函数,该函数只是将一个添加到变量中。

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

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

PS:我知道 asm.js

4

3 回答 3

30

好吧,setImmediate()它会立即运行代码,即您期望使用setTimeout(0).

不同之处在于setTimeout(0)它实际上并没有立即运行。setTimeout被“钳制”到最短等待时间(4 毫秒),这就是为什么您在测试程序中只得到 250 个计数的原因。setImmediate()确实会立即运行,因此使用它的计数器测试将高出几个数量级。

但是,您可能需要检查浏览器支持setImmediate ——它尚未在所有浏览器中可用。(当然,您可以将setTimeout(0)其用作后备,但随后您又回到了它所施加的最短等待时间)。

postMessage()也是一种选择,并且可以实现几乎相同的结果,尽管它是一个更复杂的 API,因为它旨在做更多的事情,而不仅仅是一个简单的调用循环。此外,在使用它时还需要考虑其他注意事项(有关更多信息,请参阅链接的 MDN 文章)。

MDN 站点还提到了一个 polyfill 库,用于setImmediate将其使用postMessage和其他技术添加setImmediate到尚不支持它的浏览器中。

使用requestAnimationFrame(),您的测试程序应该得到 60,因为这是标准的每秒帧数。如果你得到的不止这些,那么你的程序可能运行了超过一秒。

使用它在计数测试中永远不会得到很高的数字,因为它每秒只触发 60 次(如果硬件刷新帧速率由于某种原因较低,则更少),但如果您的任务涉及对显示器的更新那么这就是您所需要的,因此您可以使用requestAnimationFrame()它来限制它被调用的次数,从而为程序中的其他任务释放资源。

这就是requestAnimationFrame()存在的原因。如果你关心的只是让你的代码尽可能频繁地运行,那么不要使用requestAnimationFrame(); 使用setTimeoutorsetImmediate代替。但这不一定是性能的最佳选择,因为它会消耗浏览器执行其他任务所需的处理器能力。

归根结底,性能不仅仅是让某样东西运行最多次数。它是关于使用户体验尽可能流畅。这通常意味着对您的调用循环施加限制。

于 2013-11-11T13:26:48.433 回答
7

仍然处于异步状态的最短延迟是 fromMutationObserver但它是如此之短以至于如果你继续调用它,UI 将永远没有机会更新。

所以技巧是在偶尔使用更新 UIMutationObserver时使用增加值,requestAnimationFrame但这是不允许的。

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();
于 2013-11-11T20:32:04.277 回答
1

postMessage()按照本博客中的说明使用。

于 2013-11-11T13:45:10.790 回答