递归setTimeout调用会导致闭合链内存泄漏吗?

时间:2019-07-09 15:12:02

标签: javascript recursion memory-leaks settimeout

我有以下情况:

LocalDB instance "MSSQLLocalDB" started.
Private LocalDB instance "MSSQLLocalDB" shared with the shared name: "MSSQLLocalDBShare".

Name:               MSSQLLocalDB
Version:            13.1.4001.0
Shared name:        MSSQLLocalDBShare
Owner:              fv-az8\VssAdministrator
Auto-create:        Yes
State:              Running
Last start time:    7/9/2019 3:36:04 PM
Instance pipe name: np:\\.\pipe\LOCALDB#238E1FEF\tsql\query

例如,如果我们在Chrome控制台中运行以下代码,则会获得以下堆栈跟踪

let func = () => {
  //...
  let id = setTimeout(() => {
    console.trace();
    clearTimeout(id);
    func();
  }, 2000);
}

func();

每次迭代都会增加。最终,它达到了最高点(我认为在35次迭代之后),该链似乎停止增长,但是我很好奇它只是Chrome而不显示它。到底是什么情况?

1 个答案:

答案 0 :(得分:1)

  

递归setTimeout调用会导致闭合链内存泄漏吗?

不。每次触发计时器后,浏览器中的计时器子系统都会释放其与计时器功能的链接,而该链接又会将其链接释放至创建该计时器的环境,从而允许它们都被回收。

  

每次迭代都会增加。最终,它达到了一个最高点(我认为在35次迭代之后),该链似乎停止增长了,但是我很好奇它是否只是Chrome而不显示它。到底是什么情况?

这是标准的内存管理,根据JavaScript引擎对内存管理的启发式方法来清理事物,但并不总是主动地清理事物。我怀疑如果您反复按一下devtools的“收集垃圾”按钮(在“内存”选项卡上),您会发现它回到了接近基线的水平。

可能阻止V8返回接近基线的一件事是V8的漂亮async stack traces。它们被宣传为“零成本”,但当然不能完全做到这一点,因为它们必须跟踪异步堆栈信息(即使只是字符串)。