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

我有一个build立在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时,会发生这种types的行为

 ab -c 100 -n 10000000 -k http://localhost:1337/invalid/url 

我不能真正使用节点检查器来跟踪是什么原因导致如此剧烈的内存增长,因为它会在获取堆快照之前请求完整的gc。

追踪导致这种快速记忆增长的原因是什么?

如何找出哪些物体存活清除,但不生存标记扫描gc?

谢谢,

更新1所以没有办法看到中年人被清除的内容。 这里是提示,如果在清除过程中看到快速内存增加,但是随着标记和清除而突然下降,则意味着您的代码会在大的空间中创build数据。 长堆栈跟踪例如。 Restify会生成应在生产中禁用的巨大堆栈跟踪。

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

node --expose-gc script.js

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

global.gc();

当手动执行垃圾回收时,您可以应用多重快照技术:

  • 取一个Snap之前,一个Snap之后GC
  • 然后应用优化
  • 那么之前的一个Snap,GC之后的一个Snap

快照允许跟踪导致内存增长的原因。 目标是与第一个“捕捉GC后”相比,第二个“捕捉GC后”有更好的结果。

我的最佳知识是没有简单的方法来看中年的内容。 但是,如果在清除过程中看到快速内存增加,而在标记和清除发生时突然下降,则这通常意味着您的代码会在大堆空间中创build对象。 长string例如。

纠正产生巨大的堆栈跟踪与每个错误对象,这是足够大,不能适应新的空间,因此被标记和扫描忽略。