【问题标题】:Node.js: Are there optimizations for tail calls in async functions?Node.js:异步函数中的尾调用是否有优化?
【发布时间】:2018-08-16 09:00:13
【问题描述】:

我正在使用 Node v8.10.0

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

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

代码有内存泄漏,通过将其更改为立即修复:

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

我很惊讶它确实有效,因为在上述问题中,它清楚地说明了 Node 8.x 不支持 TCO。那么这里有什么特别的事情可以实现 TCO 吗?还是因为它在后台使用了一个生成器,而 return 将生成器标记为完成,所以可以丢弃堆栈?

【问题讨论】:

    标签: node.js recursion tail-recursion


    【解决方案1】:
    async function processBatch(nthBatch) {
        // do a bunch of async work and build up variables
        await processBatch(nthBatch + 1);
    }
    

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

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

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

    【讨论】:

      猜你喜欢
      • 2016-09-10
      • 2017-04-18
      • 2014-06-09
      • 1970-01-01
      • 2019-01-20
      • 1970-01-01
      • 2015-01-22
      • 2018-01-04
      • 2020-10-21
      相关资源
      最近更新 更多