Node.js 如何避免在清除gc期间快速增加内存?

Node.js 如何避免在清除gc期间快速增加内存?,node.js,memory,garbage-collection,restify,node-inspector,Node.js,Memory,Garbage Collection,Restify,Node Inspector,我有一个基于restify的应用程序。我没有内存泄漏,但是在清除gc期间内存增长很大,然后是重量级标记扫描gc并清理内存 它会影响我的应用程序的性能 [2268] 266859 ms: Scavenge 61.5 (119.5) -> 46.0 (119.5) MB, 2.2 ms [allocation failure]. [2268] 267084 ms: Scavenge 63.7 (119.5) -> 48.3 (119.5) MB, 6.2 ms [allocati

我有一个基于restify的应用程序。我没有内存泄漏,但是在清除gc期间内存增长很大,然后是重量级标记扫描gc并清理内存

它会影响我的应用程序的性能

[2268]   266859 ms: Scavenge 61.5 (119.5) -> 46.0 (119.5) MB, 2.2 ms [allocation failure].
[2268]   267084 ms: Scavenge 63.7 (119.5) -> 48.3 (119.5) MB, 6.2 ms [allocation failure].
[2268]   267289 ms: Scavenge 66.0 (119.5) -> 50.6 (119.5) MB, 2.6 ms [allocation failure].
[2268]   267504 ms: Scavenge 68.3 (119.5) -> 52.8 (119.5) MB, 2.4 ms [allocation failure].
[2268]   267700 ms: Scavenge 70.5 (119.5) -> 55.1 (119.5) MB, 2.7 ms [allocation failure].
....

[2268]   275913 ms: Scavenge 154.2 (183.5) -> 138.8 (183.5) MB, 2.4 ms [allocation failure].
[2268]   276161 ms: Scavenge 157.5 (185.5) -> 142.1 (185.5) MB, 2.7 ms (+ 2.4 ms in 18 steps since last GC) [allocation failure].
[2268]   276427 ms: Scavenge 159.8 (187.5) -> 144.3 (187.5) MB, 2.5 ms (+ 36.3 ms in 236 steps since last GC) [allocation failure].
[2268]   276494 ms: Mark-sweep 147.7 (188.5) -> 43.7 (121.5) MB, 20.1 ms (+ 45.1 ms in 298 steps since start of marking, biggest step 0.5 ms) [GC interrupt] [GC in old space requested].
当我试图访问不存在的url时,就会发生这种行为

ab -c 100 -n 10000000 -k http://localhost:1337/invalid/url
我不能真正使用node inspector来跟踪导致如此剧烈的内存增长的原因,因为它将在获取堆快照之前请求完整的gc

我可以选择哪些方法来跟踪导致如此快速的内存增长的原因

如何找出哪些对象在清除后仍能生存,而在标记扫描gc中则不能生存?

谢谢


更新1因此无法查看中年清除内容。这里有一个提示,如果您在清除过程中看到内存快速增加,但随着mark&sweep的出现,内存突然下降,那么这意味着您的代码将在大空间中创建数据。例如,长堆栈跟踪。Restify生成巨大的堆栈跟踪,应该在生产中禁用

您可以尝试使用选项
-–expose gc
运行节点脚本:

节点--公开gc script.js

这允许从JS中手动触发垃圾收集:

global.gc()

手动强制执行垃圾收集时,可以应用多快照技术:

  • 在GC之前拍一张快照,在GC之后拍一张快照
  • 然后应用优化
  • 然后在GC前一个快照,在GC后一个快照
快照允许跟踪导致内存增长的原因。 目标是获得更好的第二次“GC后捕捉”结果,
与第一个“GC后捕捉”相比

据我所知,没有简单的方法可以查看中年内容。然而,如果您看到在清除期间内存快速增加,然后在标记和扫描发生时内存突然下降,那么这通常意味着您的代码在较大的堆空间中创建对象。例如,长字符串


Convertive会对每个错误对象生成巨大的堆栈跟踪,这些错误对象大到无法放入新空间,因此mark&sweep会忽略它们。

很抱歉这个愚蠢的问题,但我如何在不调用gc的情况下拍摄快照?在执行节点应用程序之后,启动节点检查器并连接到
http://127.0.0.1:8080/debug?port=5858
(或者您的主机而不是本地主机)使用Chrome开发工具,然后进入“配置文件”选项卡。您将在那里找到“获取堆快照”和“记录堆分配”。是的,这就是我要介绍的内容。我在日志中看到,在生成完整快照之前,只有在获取堆快照时,才会自动强制执行完整的垃圾收集。换句话说:“记录堆分配”。它将在整个录制过程中拍摄快照,然后在最后拍摄最后一张快照。奇怪的是,我仍然只看到在堆分配快照期间调用的Mark sweep gc