Node.js虚拟内存在使用子进程时不断增加

时间:2016-03-28 21:08:46

标签: javascript node.js v8 heap-memory child-process

我正在使用spawn-child npm包来生成一个shell,我运行一个最初构建在C ++上的二进制文件。我为二进制文件提供了Stdin,然后二进制文件将每秒发送一次Stdout。在节点部分,一旦我开始从二进制文件接收Stdout,我就有一个on监听器,它看起来像stdout.on('data', function (data) {}),我将这些数据发送到SSE通道。

一切都运行良好,但主要关注的是节点进程的持续内存增长,当我每次用Stdin命中二进制时,我会看到。我已经概述了我的代码看起来如何,是否有一种优雅的方式来控制这种内存增长,如果是这样请分享。

var sseChannel = require('sse-channel'),
    spawnCommand = require('spawn-command'),
    cmd = 'path to the binary file',
    globalArray = [],
    uuid = require('uuid');

module.exports = function(app) {
  var child = spawnCommand(cmd),
    privateChannel = new sseChannel({
      historySize: 0,
      cors: {
        origins: ['*']
      },
      pingInterval: 15 * 1000,
      jsonEncode: false
    });
  srvc = {
    get: function(req, res) {
      globalArray[uuid.v4()] = res;
      child.stdin.write('a json object in a format that is expected by binary' + '\n'); // req.query.<queryVal>
      child.stdout.on('data', function(data) {
        privateChannel.send(JSON.stringify(data));
      });
    },
    delete: function(sessionID) {
       var response = globalArray[sessionID];
       privateChannel.removeClient(response);
       response.end();
       delete globalArray[sessionID];
    }
  }
}

此代码只是为了枚举它在应用中的外观。在这种情况下,点击Run代码段不起作用。

我以2个不同的间隔收集了heapdump,这就是统计数据的外观,Typed Array值大幅增加,可以做些什么来维持或抑制Typed Array的增长,

enter image description here

enter image description here

1 个答案:

答案 0 :(得分:5)

问题在于,您正在生成一个进程,然后为您的http服务器的每个请求添加一个新的data事件处理程序,该请求永远不会被删除。所以这就解释了为什么即使在gc之后内存使用也不会下降。

另一个(无关的)问题是,如果您使用单个子进程处理多个传入请求,则可能会遇到混合不同请求的响应的问题(您不能假设一个data事件将包含特定请求的数据)。如果子进程是基于node.js的,您可以使用它设置ipc通道,然后只是来回传递常规JavaScript值,而不是设置stdout处理/解析。如果子节点不是基于node.js的,或者您想要一个替代(no-ipc)解决方案,则可以设置一个队列,将所有请求推送到该队列,然后使用一个处理队列并按顺序响应每个请求的函数(只有在您确定已收到当前请求的子进程的所有输出后,才会转到下一个请求。)

如果您认为子进程仅用于单个请求,则需要调整代码以针对每个请求生成一次(在spawn()内移动get())。