Redis
 sql >> Database >  >> NoSQL >> Redis

Il publisher redis del nodo consuma troppa memoria

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.