Node.js垃圾回收(GC)标记-压缩

4

我遇到一个使用内存字典的应用程序问题(通过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
1个回答

1

你尝试过使用REDIS或Membase来比较性能吗?就我所知,你已经达到可以被视为内存数据库的水平,因此你可以尝试与实际使用其中一个进行比较。


我没有这样做,但在我的情况下,这不可行。关键是,如果我缓存不可变数据,那么我可以这样编写应用程序(即同步方式):user.item = storage.get('Item', itemId)使用任何类型的外部存储都将使我采用异步方法。此外,我在应用程序中发现了一个漏洞,因此问题有所缓解。 - Prologus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接