为什么传递给 winston 的字符串会保存在内存中、泄漏并最终使 node.js 进程崩溃?

Ron*_*het 10 javascript memory-leaks node.js google-chrome-devtools winston

我正在检查由node-heapdump @0.3.14创建的堆快照,该快照在内核为 4.14.123-86.109.amzn1.x86_64 的 Amazon Linux 中的 Node.js 10.16.0 上运行。堆快照是 1GB,好消息是,字符串明显消耗了其中的大部分,使用了 750MB 的浅层和保留大小。

大多数这些字符串都必须由 winston(winston@3.2.1、winston-transport@4.3.0、winston-logsene@2.0.7)记录,日志级别 ( silly) 低于我的应用程序的最低级别 ( debug)。所以,每秒几十次,

  • 我建立了一个日志字符串。
  • 我将它传递给winston.loglogLevel silly
  • 没有日志发生(正如预期的那样,silly< debug)。

预期:字符串被 GC 处理,生活还在继续。

实际:字符串在内存中累积,未 GC,节点 OOM 为最大堆大小 (1.4GB)。


我正弦确实漏了。我所描述的不是两个普通 GC 之间的名义操作,因为查看快照中字符串的内容,我看到了很多变化,就我的应用而言,这些变化只能来自几个小时的运行。

此外,devtools有时会报告大量的这些字符串大小(23MB的字符串,实际上是1KB),和家丁树是堆积如山,与> 18000级水平的next内部对象的方法messagechunk(见下图)。

所以,我的两个问题是:

  1. 为什么 winston 将这些字符串保存在内存中?我有一个想法:也许 winston 将消息保存在队列/缓冲区中,因为级别太低而不会记录,并且从不刷新队列?
  2. 这个堆快照中发生了什么?我的 1KB 小字符串怎么会有 23MB 的浅/保留大小?!这是怎么回事在这个疯狂的家臣树/谁是这些任何想法next/ message/chunk对象属于哪一种?

可提供额外信息。谢谢!

具有疯狂大小和保留器的节点堆快照中的温斯顿字符串

Esp*_*pen 1

这是 Winston 中与其使用流的方式相关的错误。它已在拉取请求中修复,您可以在此处阅读有关该问题和修复的更多信息: https: //github.com/winstonjs/winston/issues/1871