你的节点正在泄漏内存?setTimeout 可能是原因

主要观点:在 Node 中使用setTimeoutAPI 易造成内存泄漏,Timeout对象内部实现细节会导致对象存活时间过长,从而引发内存泄漏问题,尤其是与AsyncLocalStorage结合使用时。

关键信息

  • 在浏览器中setTimeout返回的令牌是number,而在 Node 中是Timeout对象,该对象内部持有一些超时实现的内部信息,导致垃圾回收器不会收集相关对象及其引用的内容。
  • AsyncLocalStorage会将额外状态附加到所有触发的超时上,使用越多AsyncLocalStorage,不清除超时就会持有越多“东西”。
  • 修复该问题的简单方法是持有底层 ID 而不是Timeout对象,但目前 Node 存在一个bug导致此方法不可行。
  • 可以通过 Monkey-Patch 方式在超时完成时强制清除超时或间隔来避免泄漏,但这会对setTimeoutsetInterval创建的每个定时器产生轻微影响。
  • 也可以在不再需要超时令牌时手动删除它们。
  • 像 Next.js 这样的项目也在尝试通过定期修补setTimeoutsetInterval来避免内存泄漏。
  • AsyncLocalStorage很有用,但容易意外持有内存,Node 可能需要改进以避免暴露内部Timeout对象,生态系统也需考虑摆脱上下文状态。

重要细节

  • 示例代码展示了MyThing类中使用setTimeoutclearTimeout的方式,以及AsyncLocalStorageTimeout对象的结合使用。
  • 提到了kHasPrimitive属性用于判断Timeout对象是否持有原始 ID。
  • 解释了console.log会意外持有调用的异步本地存储的相关问题。
  • 标签为javascript
阅读 23
0 条评论