2016-03-28 9 views
4

私は元々C++でビルドされたバイナリファイルを実行するシェルを起動するためにspawn-child npmパッケージを使用しています。私はStdinをバイナリに提供し、バイナリはStdoutを毎秒送信します。ノード部分では、バイナリからStdoutの受信を開始すると、私はonリスナを持っています。これはstdout.on('data', function (data) {})のようなもので、これらのデータをSSEチャネルに送ります。子プロセスを使用している間にNode.js仮想メモリが絶えず増加します

すべてがうまくいきますが、大きな懸念は、ノードプロセスの一定のメモリ増加です。これは、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]; 
 
    } 
 
    } 
 
}

このコードは、ちょうどそれがアプリでどのように見えるかを列挙することです。この場合、実行コードスニペットを押しても機能しません。

私は2回の異なる間隔でheapdumpを収集し、これは統計が見える、型指定された配列値の大幅な増加がある方法です、型付き配列の成長を維持または抑制するために何を行うことができる、

enter image description here

enter image description here

+0

リクエストごとに 'srvc.get()'を呼び出していますか? – mscdex

+0

うん、それは正しいです。リクエストが行われるたびに、バイナリにstdinが提供され、stdout 'on'リスナーがデータをログに記録します。 – Sai

+0

'srvc'の有効範囲は何ですか?すべてのモジュール呼び出しで目的に合わせて上書きしていますか?フルコードをお知らせください。 – Bergi

答えて

5

問題は、あなたが一度プロセスを生成し、その後削除されることは決してありませんHTTPサーバーへの要求ごとに新しいdataイベントハンドラを追加しているということです。これはなぜgcの後でもメモリ使用量が決して低下しない理由を説明します。

別の(無関係な)問題は、複数の着信要求を処理するために、あなたの単一の子プロセスを使用している場合、あなたは1つのdataイベントが含まれていることを前提とすることはできません(別の要求に対して応答を混合の問題に実行できることですのみ特定の要求のデータ)。子プロセスがnode.jsベースの場合は、ipcチャネルを設定して、stdout処理/解析を設定するのではなく、通常のJavaScript値を前後に渡すことができます。子がnode.jsベースでないか、代替(no-ipc)ソリューションが必要な場合は、すべての要求がプッシュされるキューを設定し、キューを処理して各要求にシリアルに応答する機能を持つことができます(現在のリクエストの子プロセスからすべての出力を受け取ったとしたら、次のリクエストに移動するだけです)。

代わりに、1つのリクエストに対してのみ子プロセスを使用する場合は、代わりにリクエストごとに1回スポーンするようにコードを調整する必要があります(spawn()get()に移動)。

+0

私はあなたが提案していた厳密な解決策を試しましたが、それの欠点は、リクエストごとにプロセスが生成された場合、私はバイナリファイル(C++アプリケーション)を1つのリクエストごとに実行することになります。ケース100の要求を処理するので、多くのプロセスが非常に高価になることがあります。 – Sai

+1

だから私はその二次的な問題(複数の解決策を挙げました:use ipcやキューを含む)です。 – mscdex

+0

このユースケースでは、私はイベントストリームを扱っています。リクエストが行われたとき、つまりstdinが子プロセスに送信された場合、プロセスはデータ(stdouts)を連続して出力します。現在のリクエストが行われた後のリクエストを作成する..私はリクエストを作成し、それがアクティブになることを意味し、アクティブなリクエストを許可する必要があります。 – Sai

関連する問題