繁体   English   中英

为什么在这种情况下,本机承诺似乎比chrome中的回调更快?

[英]Why in this case native promises seems to be faster than callbacks in chrome?

这是jsperf: http ://jsperf.com/promise-vs-callback

回调案例(211 Ops / s):

// async test
var d = deferred;

function getData(callback) {
  setTimeout(function() {
    callback('data')
  }, 0)
}

getData(function(data) {
  d.resolve()
})

承诺案例(614 ops / s):

// async test
var d = deferred;

function getData() {
  return new Promise(function(resolve) {
    setTimeout(function() {
      resolve('data')
    }, 0);
  })
}

getData().then(function(data) {
  d.resolve()
})

如你所见,承诺更快,但他们有更多的代码。 问题是为什么会发生这种情况。

这里deferred是由jsperf定义的,以显示它作为异步测试的完成。

看起来神奇的技巧在于chrome如何设置setTimeout(fn, 0)的最小延迟。

我搜索了它,我发现了这个: https//groups.google.com/a/chromium.org/forum/#!msg/blink-dev/Hn3GxRLXmR0/XP9xcY_gBPQJ

我引用了重要的部分:

定时器钳位的工作方式是每个任务都有一个相关的定时器嵌套级别。 如果任务源自setTimeout()或setInterval()调用,则嵌套级别大于调用setTimeout()的任务的嵌套级别或该setInterval()的最近迭代的任务,否则为零。 只有嵌套级别为4或更高时,4ms钳位才适用。 在事件处理程序,动画回调或未深度嵌套的计时器的上下文中设置的计时器不受钳位。

在回调的情况下,setTimeout在另一个setTimeout的上下文中递归调用,因此最小超时为4ms。 在promise的情况下,setTimeout实际上不是递归调用的,所以最小超时为0(实际上不会是0,因为其他东西也必须运行)。

那么我们怎么知道setTimeout是递归调用的呢? 好吧,我们可以在jsperf或只使用benchmark.js进行实验:

// async test
deferred.resolve()

这将导致Uncaught RangeError: Maximum call stack size exceeded. 这意味着,一旦调用deferred.resolve,测试就会在同一个tick / stack上再次运行。 所以在回调的情况下,setTimeout在它自己的调用上下文中被调用并嵌套在另一个setTimeout中,这将把最小超时设置为4ms。

但是在承诺的情况下, .then回调的下一个节拍后,根据承诺规范调用,V8 不setTimeout的呼叫下打勾回调后使用 它使用的东西,必须类似于process.nextTick在或的NodeJS setImmediate ,而不是setTimeout的。 这会将setTimeout嵌套级别重置为0并使setTimeout延迟0ms。

首先,您的基准测试设计错误。 它只会测量最小的setTimeout值,而不是回调和promises之间的性能差异。

最小延迟为4ms因此结果不能超过每秒250次操作。 以某种方式调用new Promise正在消除最小的4ms延迟。

如果你想衡量承诺和回调差异,你需要消除这种不自然的瓶颈。 因此,您不仅要测量并发级别为1,还要在每次调用之间等待4ms。

JSPErf并不容易设置并发性,但这里的并发性为1000:

http://jsperf.com/promise-vs-callback/7

正如Esailija指出的那样,它与Promise中奇怪的setTimeout优化有关。 另请参阅使用更快的setTimeout替代方案制作的相同基准测试: http//jsperf.com/promise-vs-callback/8它提供了更多预期结果

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM