Ci sono due domande qui.
Perché il programma richiede così tanta memoria?
Penso che sia dovuto alla mancanza di contropressione.
Il tuo script invia solo 1M di comandi di pubblicazione a Redis, ma non elabora alcuna risposta a questi comandi (che quindi vengono semplicemente scartati da node_redis). Poiché non attende mai alcuna risposta, lo script accumulerà molto contesto in memoria per tutti questi comandi. node_redis deve mantenere un contesto per tenere traccia dei comandi e associare comandi e risposte Redis. Node.js è più veloce per accodare i comandi, rispetto al sistema per trasmettere quei comandi a Redis, elaborarli, creare risposte e trasmettere le risposte a node.js. Il contesto è quindi in crescita, e rappresenta molta memoria.
Se vuoi mantenere il consumo di memoria a un livello accettabile, devi ridurre il codice per dare la possibilità a node.js di elaborare le risposte Redis. Ad esempio, lo script seguente elabora anche 1 milione di elementi, ma li pubblica come batch di 1000 elementi e attende le risposte ogni 1000 elementi. Pertanto consuma pochissima memoria (il contesto contiene al massimo 1000 comandi in sospeso).
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);
La memoria può essere rilasciata?
Di solito, non può. Come tutti i programmi C/C++, node.js utilizza un allocatore di memoria. Quando la memoria viene liberata, non viene rilasciata al sistema, ma all'allocatore di memoria. In genere, l'allocatore di memoria non è in grado di restituire al sistema la memoria inutilizzata. Tieni presente che non è una perdita, perché se il programma esegue una nuova allocazione, la memoria verrà riutilizzata.
La scrittura di un programma C/C++ che può effettivamente rilasciare memoria al sistema implica generalmente la progettazione di un allocatore di memoria personalizzato. Pochi programmi C/C++ lo fanno. Inoltre, node.js include un Garbage Collector con v8, quindi dovrebbe imporre ulteriori vincoli alla politica di rilascio della memoria.