Node.js:是否对异步函数中的尾调用进行了优化? [英] Node.js: Are there optimizations for tail calls in async functions?

查看:67
本文介绍了Node.js:是否对异步函数中的尾调用进行了优化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的是 Node v8.10.0

I'm using Node v8.10.0

上述问题解释了 Node.js 如何不再支持 TCO.不过,我最近遇到了这样一个函数的问题:

The above question explains how Node.js doesn't support TCO anymore. I recently experienced an issue with a function like this though:

async function processBatch(nthBatch) {
    // do a bunch of async work and build up variables
    await processBatch(nthBatch + 1);
}

该代码存在内存泄漏,通过将其更改为:

The code had a memory leak which was immediately fixed by changing this to:

async function processBatch(nthBatch) {
    // do a bunch of async work and build up variables
    return processBatch(nthBatch + 1);
}

我很惊讶它确实有效,因为在上述问题中,它清楚地说明了 Node 8.x 不支持 TCO.那么,是否有什么特别的事情可以在这里实现 TCO?或者是因为它在引擎盖下使用了一个生成器并且返回标记生成器已完成,因此可以丢弃堆栈?

I'm surprised that actually worked, because in the question described above, it clearly explains that TCOs aren't supported in Node 8.x. So is there something special going on that enables a TCO here? Or is it because it's using a generator under the hood and the return marks the generator as done, so the stack can be discarded?

推荐答案

async function processBatch(nthBatch) {
    // do a bunch of async work and build up variables
    await processBatch(nthBatch + 1);
}

这段代码会导致内存泄漏,因为注释中声明的变量不能被垃圾回收,因为解释器不知道它们将不再需要.例如解释器此时并不知道 await 之后没有一行可能需要所有这些声明的变量.

This snippet results in a memory leak because the variables declared at the comment cannot be garbage collected, because the interpreter doesn't know that they won't be needed again. e.g. the interpreter doesn't know at that point that there isn't a line after the await that might need all those declared variables.

async function processBatch(nthBatch) {
    // do a bunch of async work and build up variables
    return processBatch(nthBatch + 1);
}

在这个例子中,函数被返回,所以垃圾收集器可以安全地清理方法中声明的变量.请注意,堆栈会一直存在,如果此递归函数迭代次数过多,则会抛出 Maximum call stack size exceeded 错误,但声明的变量存在于堆中,因此可以在同时进行垃圾回收保持堆栈信息完整.

In this example, the function is returned, so the garbage collector can safely clean up the variables declared in the method. Note that the stack sticks around, and if this recursive function has too many iterations there will be a Maximum call stack size exceeded error thrown, but the variables declared live in the heap and so can be garbage collected while keeping the stack information intact.

这篇关于Node.js:是否对异步函数中的尾调用进行了优化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆