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

时间:2015-08-28 12:47:48

标签: 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 [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 所以没有办法看到中年人的清除内容。这是提示,如果你在清除过程中看到快速内存增加,但随后它会随着标记和扫描而突然下降,那么这意味着你的代码会在大空间中创建数据。例如,长堆栈跟踪。 Restify会生成巨大的堆栈跟踪,应该在生产中禁用。

2 个答案:

答案 0 :(得分:3)

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

node --expose-gc script.js

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

global.gc();

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

  • 之前采取一个Snap,GC之后采用一个Snap
  • 然后应用优化
  • 然后一次Snap,一次点击GC后

快照允许跟踪导致内存增长的原因。 我们的目标是在GC"之后获得第二个" Snap的更好结果, 与GC"之后的第一个" Snap相比。

答案 1 :(得分:0)

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

Rectify会为每个Error对象生成巨大的堆栈跟踪,这些跟踪大到足以不适合新空间,因此可以通过mark& sweep来忽略。