我遇到一个使用内存字典的应用程序问题(通过new Constructor(bla,fla,pla)实例化)。一旦驻留内存大小接近100-150 Mbs,标记压缩阶段就需要超过一秒钟。每增加一百兆,就会再添加一秒。
可以通过运行以下内容来重现此行为:
node --trace_gc test-memory.js
test_memory.js:
var http = require('http'),
Construct = function () {
this.theField = Math.random();
},
storage = [];
http.createServer(function (req, res) {
var i = 100000;
while (--i) {
storage.push(new Construct());
}
res.end('Lots of data generated.');
}).listen(1337, '127.0.0.1');
然后运行curl localhost:1337一段时间,观察以下内容:
Scavenge 143.5 -> 143.5 MB, 2 ms.
Mark-sweep 143.5 -> 143.5 MB, 943 ms.
Mark-compact 143.5 -> 143.5 MB, 1306 ms.
Scavenge 143.5 -> 143.5 MB, 2 ms.
Mark-sweep 143.5 -> 143.5 MB, 937 ms.
Mark-compact 143.5 -> 143.5 MB, 1189 ms.
Scavenge 143.5 -> 143.5 MB, 2 ms.
Mark-sweep 143.5 -> 143.5 MB, 935 ms.
Mark-compact 143.5 -> 143.5 MB, 1191 ms.
Scavenge 143.5 -> 143.5 MB, 1 ms.
Mark-sweep 143.5 -> 143.5 MB, 1015 ms.
Mark-compact 143.5 -> 143.5 MB, 1218 ms.
Scavenge 143.5 -> 143.5 MB, 2 ms.
Mark-sweep 143.5 -> 143.5 MB, 937 ms.
Mark-compact 143.5 -> 143.5 MB, 1195 ms.
据我所知,垃圾回收器试图移动那些不会被释放的对象。我找到的唯一解决方案是将这些对象移到缓冲区中,但对于我的应用程序来说,这意味着需要使用JSON.stringify | JSON.parse,这很可能会导致更多的CPU时间开销。而且这还需要进行相当大的重写。
我知道这可能更多是v8的问题,但也许有一些方式可以规避GC的限制,使得未被释放的对象不会被移动?
node.js版本为0.6.11
user.item = storage.get('Item', itemId)
使用任何类型的外部存储都将使我采用异步方法。此外,我在应用程序中发现了一个漏洞,因此问题有所缓解。 - Prologus