ここには2つの質問があります。
プログラムがこれほど多くのメモリを必要とするのはなぜですか?
背圧が足りないからだと思います。
スクリプトは1Mの公開コマンドをRedisに送信するだけですが、これらのコマンドへの応答は処理されません(したがって、node_redisによって破棄されるだけです)。応答を待つことはないため、スクリプトはこれらすべてのコマンドのメモリに多くのコンテキストを蓄積します。 node_redisは、コマンドを追跡するためのコンテキストを維持し、Redisコマンドと応答を関連付ける必要があります。 Node.jsは、システムがそれらのコマンドをRedisに伝達し、処理し、応答を作成し、応答をnode.jsに戻すよりも、コマンドをエンキューする方が高速です。したがって、コンテキストは成長しており、多くのメモリを表しています。
メモリ消費量を許容レベルに維持したい場合は、コードを絞り込んで、node.jsがRedis応答を処理する機会を与える必要があります。たとえば、次のスクリプトも1Mアイテムを処理しますが、それらを1000アイテムのバッチとして公開し、1000アイテムごとに応答を待ちます。したがって、メモリの消費量はごくわずかです(コンテキストには最大1000個の保留中のコマンドが含まれます)。
var redis = require("redis"),
publisher = redis.createClient();
function loop( callback ) {
var count = 0;
for ( i=0 ; i < 1000; ++i ) {
publisher.publish("rChat", i, function(err,rep) {
if ( ++count == 1000 )
callback();
});
}
}
function loop_rec( n, callback ) {
if ( n == 0 ) {
callback();
return;
}
loop( function() {
loop_rec( n-1, callback );
});
}
function main() {
console.log("Hello");
loop_rec(1000, function() {
console.log("stopped sending messages");
setTimeout(function(){publisher.end();},1000);
return;
});
}
publisher.ping(main)
setTimeout(function() {
console.log("Keeping console alive");
}, 1000000);
メモリを解放できますか?
通常はできません。すべてのC/C ++プログラムと同様に、node.jsはメモリアロケータを使用します。メモリが解放されると、システムには解放されませんが、メモリアロケータに解放されます。通常、メモリアロケータは未使用のメモリをシステムに戻すことはできません。プログラムが新しい割り当てを実行すると、メモリが再利用されるため、リークではないことに注意してください。
システムに実際にメモリを解放できるC/C ++プログラムを作成するには、通常、カスタムメモリアロケータを設計する必要があります。それを行うC/C++プログラムはほとんどありません。さらに、node.jsにはv8のガベージコレクターが含まれているため、メモリ解放ポリシーに追加の制約を課す必要があります。