NodeJS:向child_processes发送消息时内存不足

时间:2013-12-31 15:10:35

标签: node.js

我的目标是创建一个父进程,无限期地将消息流式传输到子进程。为了测试这一点,我尝试使用以下代码将150M消息发送给不执行任何操作的子进程。

  1. (可能的答案在下面编辑)为什么这段代码会耗尽内存?
  2. 我正在使用ofe模块,但我不知道在生成的heapdump中要查找什么,我可以使用什么方法搜索heapdump中的线索?
  3. 代码:

    server.js

    //  After 20M messages i get: 
    //  FATAL ERROR: CALL_AND_RETRY_2 Allocation failed - process out of memory
    
    
    var cp = require('child_process');
    var xrange = require('xrange');
    var maxChildren = require('os').cpus().length;
    var util = require('util');
    require('ofe').call();
    
    var childError = function(err) {
        console.log('Error: ' + err);
    };
    
    var childExit = function(code, signal) {
        console.log('Exit Code: ' + code);
        console.log('Exit Signal: ' + signal);
    };
    
    var childClose = function(code, signal) {
        console.log('Close Code: ' + code);
        console.log('Close Signal: ' + signal);
    };
    
    var childDisconnect = function() {
        console.log('Disconnect');
    };
    
    var childMessage = function(msg, handle) {
        console.log('Msg: ' + msg);
    };
    
    var createChild = function(){
        var child = cp.fork("./child");
        child.on('error', childError);
        child.on('exit', childExit);
        child.on('close', childClose);
        child.on('disconnect', childDisconnect);
        child.on('message', childMessage);
        console.log("Child Created: " + child.pid);
        return child;
    }
    
    var createChildren = function(){
        var children = [];
        xrange(maxChildren).each(function(i) {
            children[i] = createChild();
        });
        return children;
    }
    
    var sendMessages = function(children) {
    xrange(150000000).each(function(num) {
    var idx = num % maxChildren;
    if (num % 1000000 == 0) {
      console.log(num);
    }
    children[idx].send(num);
    });
    };
    

    child.js(内容)

    process.on('message', function(msg) {});
    

    答案

    由于此代码是异步的,因此父进程会将所有消息发送给子进程,而无需等待它们被处理,这似乎会使客户端过载。我相信解决方案是从客户端发回消息,以便在处理后“拉”下一个数字。假设这是答案,我有一个跟进问题。

    1)我想写这个但是我不确定如何将xrange转换为生成器而没有屈服(no-harmony nodejs),是否有回调解决方案? :

    function getNextNumber(){
      //pull the next available number from the 150M
    }
    
    child.on('message',function(msg) {
      child.send(getNextNumber());
    });
    

    跟进

    如果我只是想迭代,这似乎就是这样:https://stackoverflow.com/a/5784473/1578888

    如果我正确地阅读这个替代答案,似乎将xrange调用实现为真正的生成器是不可能的预和谐:https://stackoverflow.com/a/7442013/1578888

    这是我最终使用的代码(也将server.js重命名为parent.js):

    parent.js

    var cp = require('child_process');
    var xrange = require('xrange');
    var maxChildren = require('os').cpus().length;
    var util = require('util');
    require('ofe').call();
    
    var childError = function(err) {
        console.log('Error: ' + err);
    };
    
    var childExit = function(code, signal) {
        console.log('Exit Code: ' + code);
        console.log('Exit Signal: ' + signal);
    };
    
    var childClose = function(code, signal) {
        console.log('Close Code: ' + code);
        console.log('Close Signal: ' + signal);
    };
    
    var childDisconnect = function() {
        console.log('Disconnect');
    };
    
    var childMessage = function(msg, handle) {
            //no output anymore!
        //console.log('Msg: ' + msg);
    };
    
    var createChild = function(){
        var child = cp.fork("./child.js");
        child.on('error', childError);
        child.on('exit', childExit);
        child.on('close', childClose);
        child.on('disconnect', childDisconnect);
        child.on('message', childMessage);
        console.log("Child Created: " + child.pid);
        return child;
    }
        var getNextFn = (function () {
            var i = 0
            return function(cb) {
                i = i + 1;
                if (i < 150000000) {
                    return i;
                } else {
                    return null;
                }
            }
        })();
    
    var createChildren = function(){
        var children = [];
        xrange(maxChildren).each(function(i) {
            var child = createChild();
                child.on('message', function(msg) {
                    var next = getNextFn();
                    if (next) {
                        if (next % 1000000 == 0) {
                            console.log(next + " " + new Date().toISOString());
                        }   
                        child.send(next);
                    } else {
                        child.kill();
                    }
                });
                children[i] = child;
        });
        return children;
    }
    
    var c = createChildren();
    

    child.js

    process.on('message', function(msg) {   
    process.send({});
    });
    
    process.send({});
    

0 个答案:

没有答案