Tutaj są dwa pytania.
Dlaczego program wymaga tyle pamięci?
Myślę, że wynika to z braku przeciwciśnienia.
Twój skrypt po prostu wysyła 1M poleceń publikowania do Redis, ale nie przetwarza żadnych odpowiedzi na te polecenia (które są zatem po prostu odrzucane przez node_redis). Ponieważ nigdy nie czeka na żadną odpowiedź, skrypt zgromadzi w pamięci dużo kontekstu dla wszystkich tych poleceń. node_redis musi zachować kontekst, aby śledzić polecenia i kojarzyć polecenia i odpowiedzi Redis. Node.js jest szybszy do kolejkowania poleceń, niż system ma przekazywać te polecenia do Redis, przetwarzać je, budować odpowiedzi i przekazywać odpowiedzi z powrotem do node.js. Kontekst zatem rośnie i reprezentuje dużo pamięci.
Jeśli chcesz utrzymać zużycie pamięci na akceptowalnym poziomie, musisz ograniczyć kod, aby umożliwić node.js przetworzenie odpowiedzi Redis. Na przykład poniższy skrypt przetwarza również 1 mln elementów, ale publikuje je jako partie po 1000 elementów i czeka na odpowiedzi co 1000 elementów. W związku z tym zużywa bardzo mało pamięci (kontekst zawiera maksymalnie 1000 oczekujących poleceń).
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);
Czy pamięć można zwolnić?
Zwykle nie. Jak wszystkie programy C/C++, node.js używa alokatora pamięci. Zwolniona pamięć nie jest zwalniana do systemu, ale do alokatora pamięci. Generalnie alokator pamięci nie jest w stanie zwrócić nieużywanej pamięci do systemu. Pamiętaj, że nie jest to wyciek, ponieważ jeśli program wykona nową alokację, pamięć zostanie ponownie wykorzystana.
Napisanie programu w języku C/C++, który faktycznie może zwolnić pamięć do systemu, zazwyczaj wiąże się z zaprojektowaniem niestandardowego alokatora pamięci. Niewiele programów C/C++ to robi. Co więcej, node.js zawiera garbage collector z v8, więc powinien nakładać dodatkowe ograniczenia na politykę zwalniania pamięci.