【问题标题】:Sync vs Immediate Async execution performance bench同步与立即异步执行性能基准
【发布时间】:2023-03-29 19:30:01
【问题描述】:

我对同步和异步数据转换测试的性能比较感兴趣,以防异步函数立即返回结果。这会影响执行时间吗?

为了检查这一点,我写了简单的 bench 来检查。

const { performance } = require('perf_hooks');

const data = JSON.stringify((() => {
    const obj = {};
    for (let i = 0; i < 1000; i++) {
        obj[i] = i;
    }
    return obj;
})());

function convertSync (data) {
    return JSON.parse(data);
}

async function convertAsync (data) {
    return JSON.parse(data); 
}

const REPEAT_COUNT = 10000;

performance.mark("sync_start");
for (let i = 0; i < REPEAT_COUNT; i++) {
    convertSync(data);
}
performance.mark("sync_end");

performance.mark("async_start");
Promise.resolve()
    .then(async () => {
        for (let i = 0; i < REPEAT_COUNT; i++) {
            await convertAsync(data);
        }
        performance.mark("async_end");
    })
    .then(async () => {
        performance.measure("sync", "sync_start", "sync_end");
        performance.measure("async", "async_start", "async_end");

        console.log("REPEAT_COUNT", REPEAT_COUNT);
        console.log(performance.getEntries().filter(x => x.entryType === "measure"));
    }) 

我正在使用 Node v8.11.1,没有任何转译器并得到以下结果。

PS D:\TestProjects\PerfTest\promisevssync> node .\index.js
REPEAT_COUNT 100000
[ PerformanceEntry {
    duration: 7825.5724,
    startTime: 383379071.208899,
    entryType: 'measure',
    name: 'sync' },
  PerformanceEntry {
    duration: 7836.966301,
    startTime: 383386896.834899,
    entryType: 'measure',
    name: 'async' } ]
PS D:\TestProjects\PerfTest\promisevssync> node .\index.js
REPEAT_COUNT 10000
[ PerformanceEntry {
    duration: 788.824201,
    startTime: 383405055.485299,
    entryType: 'measure',
    name: 'sync' },
  PerformanceEntry {
    duration: 798.591301,
    startTime: 383405844.370999,
    entryType: 'measure',
    name: 'async' } ]

如您所见,执行时间是相同的。对于更高的重复计数数字仍然没有太大差异,所以我相信这只是一个鼻子。这样的结果提出了两个问题:

  1. 这个测试正确吗?
  2. 为什么?

我知道我遗漏了一些东西,但似乎我忘了考虑一些基本的东西。

【问题讨论】:

  • "如果异步函数会立即返回结果......" 函数是异步的毫无意义。
  • 让我们开始吧,为什么你认为“异步”代码应该比同步版本慢?
  • 请注意,您正在使用已弃用的 perf_hooks API,该 API 在 Node 10 中不起作用。@Thomas 您可以预期异步循环本身会出现相当大的延迟,并且承诺实现效率较低。但是,这在 Node 中不是问题。
  • @Bergi,接口需要。我正在制作一些通用接口,它需要是异步的,所以我担心性能调用,因为设计接口可能会在每个循环调用中处理几千个调用。
  • @estus,您能否描述一下为什么它在 Node 中不是问题?有什么区别?

标签: javascript node.js promise async-await


【解决方案1】:

我对同步和异步数据转换测试的性能比较感兴趣,以防异步函数立即返回结果。这会影响执行时间吗?

测量结果是正确的,但请注意,测量的是同步和异步迭代的性能,而数据转换保持同步。

Node.js 有高分辨率的计时器,所以 promises 本身只引入了一点延迟 与花在convertAsync 通话上的时间相比,这可以忽略不计。

这个 10000 次迭代的测试证实了这一点:

for (let i = 0; i < REPEAT_COUNT; i++) {}

for (let i = 0; i < REPEAT_COUNT; i++) {
  await null;
}

同步循环的测量值为 0.5 毫秒,异步的测量值为 9 毫秒。

与空运行相比,大部分时间将花在JSON.parse(data)

【讨论】:

  • 也许我不清楚,但是是的,我正在查看同步和异步方法之间的增量时间,而不是绝对时间。它很小,并且想知道为什么,我确信基于 Promise 的版本,即使有立竿见影的效果,也会明显变慢,但不会慢几毫秒。如此低的偏差甚至可能被视为噪声。
  • 浏览器中的差异可能更大。由于事件循环的工作方式,它在 Node 中更有效。是的,可能是噪音。由于这个原因,一个循环可能不足以进行统计上正确的基准测试。使用npmjs.com/package/benchmark
【解决方案2】:

要使 async-await 正常工作,您的函数应该返回一个承诺,但事实并非如此。所以你得到了类似的结果,因为 convertAsync 不是真正的异步函数。在内部,javascript 所做的是将您的函数包装在已解决的承诺中,并且由于您的承诺几乎立即被解决,因此您在结果中看到的差异很小。

看看https://javascript.info/async-await

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-05
    • 2021-07-16
    相关资源
    最近更新 更多