首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在Node.js中,非并行异步循环与同步循环的性能是否存在差异?

在Node.js中,非并行异步循环与同步循环的性能是否存在差异?
EN

Stack Overflow用户
提问于 2019-04-10 01:24:24
回答 1查看 423关注 0票数 2

我将用于JavaScript的Node.js代码(v10.13.0)重构为异步/等待异步代码,该代码以前是同步的。后来我注意到,性能下降了~3倍的程序执行时间。

当将同步函数调用链转换为异步函数调用时,是否存在性能损失?

简化示例

变更同步码

代码语言:javascript
运行
复制
function fn1() {  
   return 1;
}

function fn2() { 
   return fn1();
}

(function() {
  const result = fn2();
})();

转换为异步代码:

代码语言:javascript
运行
复制
async function fn1() {  
   return 1;
}

async function fn2() { 
   return await fn1();
}

(async function() {
   const result = await fn2();
})();

有什么事件循环魔法可以使后一段代码在Node.js webapp中变慢吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-12-10 20:25:52

下面是一个更高级的基准,它使用同步或异步函数计算Fibonacci系列:

代码语言:javascript
运行
复制
async function benchmark(M = 1000000, N = 100) {
    function fibonacci_sync(num) {
        let a = 1, b = 0, temp
        while (num >= 0) {
            temp = a; a = a + b; b = temp; num--
        }
        return b
    }
    async function fibonacci_async(num) {
        let a = 1, b = 0, temp
        while (num >= 0) {
            temp = a; a = a + b; b = temp; num--
        }
        return b
    }
    timeitSync  ('sync',  M,       () => {for(let i = 0; i < N; i++) fibonacci_sync(i)})
    await timeit('async', M, async () => {for(let i = 0; i < N; i++) await fibonacci_async(i)})
}

node.js中的示例执行时间证明是2.8x慢

代码语言:javascript
运行
复制
sync:    4.753s
async:  13.359s

对于更大的M,但是更小的N = 10而不是N=100 (更短的计算,所以等待会产生更大的影响),异步函数变成14.5x慢 (ooops!!):

代码语言:javascript
运行
复制
sync:   0.499s
async:  7.258s

这是在Node v16.13.1上。基准测试的灵感来自于这篇文章:https://madelinemiller.dev/blog/javascript-promise-overhead/

为了完整起见,下面是上面使用的timeit函数:

代码语言:javascript
运行
复制
async function timeit(label, repeat, fun) {
    console.time(label)
    for (let i = 0; i < repeat; i++) await fun()
    console.timeEnd(label)
}
function timeitSync(label, repeat, fun) {
    console.time(label)
    for (let i = 0; i < repeat; i++) fun()
    console.timeEnd(label)
}

当使用async timeit而不是timeitSync度量async timeit时,在最后一个示例中,执行时间从0.499s增长到1.2s,这再次证实了async带来了很大的减速。

因此,是的,的确,异步调用可能带来性能的巨大下降,甚至是数量级的下降。每个调用都必须经过一个事件队列,其管理似乎会造成大量开销。在实现包含大量异步函数的代码时,一定要考虑到这一点。

考虑到async范式的“传染性”--一个低级函数是异步的,树上的所有调用者也必须是异步的--我很高兴JS引入了优化,允许在某些情况下(大多数情况下)立即执行await...,而不是被一次又一次地推到队列中,每两条指令一次又一次。这可能会使所有场景受益,在这些场景中,await被包装在条件中,很少需要实际停止函数,但仍然需要将函数声明为“异步”,不管“等待”到达的频率有多高。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55603430

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档