How to Request the Garbage Collector in Node.Js to Run

How to request the Garbage Collector in node.js to run?

If you launch the node process with the --expose-gc flag, you can then call global.gc() to force node to run garbage collection. Keep in mind that all other execution within your node app is paused until GC completes, so don't use it too often or it will affect performance.

You might want to include a check when making GC calls from within your code so things don't go bad if node was run without the flag:

try {
if (global.gc) {global.gc();}
} catch (e) {
console.log("`node --expose-gc index.js`");
process.exit();
}

when i manually execute the garbage collector, how can I tell when it's completed?

So I found this answer.

If you launch the node process with the --expose-gc flag, you can then call global.gc() to force node to run garbage collection. Keep in mind that all other execution within your node app is paused until GC completes, so don't use it too often or it will affect performance.

This one comments on it too.

Running global.gc() manually (enabled with node --expose_gc) would reduce memory usage by 50MB every time and would pause the app for about 400ms.

So it looks like it's synchronous and blocks until it is finished.

When does Node garbage collect?

This might not be a complete answer, but it's coming from experience and might provide some pointers. Memory leak in NodeJS is one of the most challenging bugs that most developers could ever face.

But before we talk about memory leak, to answer your question - unless you explicitly configure --max-old-space-size, there are default memory limits that would take over. Since certain phases of Garbage collection in node are expensive (and sometimes blocking) steps, depending upon how much memory is available to it, it would delay (e.g. mark-sweep collection) some of the expensive GC cycles. I have seen that in a Machine with 16 GB of memory it would easily let the memory go as high as 800 MB before significant Garbage Collections would happen. But I am sure that doesn't make ~800 MB any special limit. It would really depend on how much available memory it has and what kind of application are you running. E.g. it is totally possible that if you have some complex computations, caches (e.g. big DB Connection Pools) or buggy logging libraries - they would themselves always take high memory.

If you are monitoring your NodeJs's memory footprint - sometime after the the server starts-up, everything starts to warm up (express loads all the modules and create some startup objects, caches warm up and all of your high memory consuming modules became active), it might appear as if there is a memory leak because the memory would keep climbing, sometimes as high as ~1 gb. Then you would see that it stabilizes (this limit used to be lesser in <v8 versions).

But sometimes there are actual memory leaks (which might be hard to spot if there is no specific pattern to it).

In your case, 256 MB seems to be meeting just the minimum RAM requirements for nodejs and might not really be enough. Before you start getting anxious of memory leak, you might want to pump it up to 1.5 GB and then monitor everything.

Some good resources on NodeJS's memory model and memory leak.

  • Node.js Under the Hood
  • Memory Leaks in NodeJS
  • Can garbage collection happen while the main thread is
    busy?
  • Understanding and Debugging Memory Leaks in Your Node.js Applications

Some debugging tools to help spot the memory leaks

  • Node inspector |
    Chrome

  • llnode

  • gcore

When does the garbage collector free the 'request' object?

In this particular case request will never be garbage-collected, since you haven't read any data from response, and response has a response.req reference to request.

However, in this case:

var http = require('http');
function createRequest() {
var options = {};
var request = http.request(options, function(response) {
response.resume()
});
request.end();
}
createRequest();

request will be garbage-collected eventually after response emits end event.

marking' an object for garbage collection in NodeJS

(V8 developer here.) There's no way to do this, and you don't need to worry about it. Marking works the other way round: the GC finds and marks live objects. Dead objects are never marked, and there's no explicit act of destroying them. The GC never even looks at dead objects. Which also means that dead objects are not a burden.

"Garbage collector" really is a misleading term: it doesn't actually find or collect garbage; instead it finds non-garbage and keeps it, and everything it hasn't found it just ignores by assuming that the respective memory regions are free.

In theory, there could be a way to manually add (the memory previously occupied by) objects to the "free list"; but there's a fundamental problem with that: part of the point of automatic memory management is that automating it provides better security and stability than relying on manual memory management (with programmers being humans, and humans making mistakes). That means that by design, a GC can't trust anyone else to declare objects as unreachable; it would always insist on verifying that claim -- which is equivalent to disregarding it, as the only way to verify it is to run a full regular GC cycle.

garbage collection with node.js

Simple answer: if value of the str is not referenced from anywhere else (and str itself is not referenced from restofprogram) it will become unreachable as soon as the function (str) { ... } returns.

Details: V8 compiler distinguishes real local variables from so called context variables captured by a closure, shadowed by a with-statement or an eval invocation.

Local variables live on the stack and disappear as soon as function execution completes.

Context variables live in a heap allocated context structure. They disappear when the context structure dies. Important thing to note here is that context variables from the same scope live in the same structure. Let me illustrate it with an example code:

function outer () {
var x; // real local variable
var y; // context variable, referenced by inner1
var z; // context variable, referenced by inner2

function inner1 () {
// references context
use(y);
}

function inner2 () {
// references context
use(z);
}

function inner3 () { /* I am empty but I still capture context implicitly */ }

return [inner1, inner2, inner3];
}

In this example variable x will disappear as soon as outer returns but variables y and z will disappear only when both inner1, inner2 and inner3 die. This happens because y and z are allocated in the same context structure and all three closures implicitly reference this context structure (even inner3 which does not use it explicitly).

Situation gets even more complicated when you start using with-statement, try/catch-statement which on V8 contains an implicit with-statement inside catch clause or global eval.

function complication () {
var x; // context variable

function inner () { /* I am empty but I still capture context implicitly */ }

try { } catch (e) { /* contains implicit with-statement */ }

return inner;
}

In this example x will disappear only when inner dies. Because:

  • try/catch-contains implicit with-statement in catch clause
  • V8 assumes that any with-statement shadows all the locals

This forces x to become a context variable and inner captures the context so x exists until inner dies.

In general if you want to be sure that given variable does not retain some object for longer than really needed you can easily destroy this link by assigning null to that variable.

Garbage collection of objects using express

An object is eligible for garbage collection as long as its reference stops being used.

Since person reference isn't passed anywhere, the variable stops to exist at the end of route handler function, the memory it uses will be released on next garbage collection.

If requests are done frequently, it's possible that memory will be occupied with a bunch of Person instances until they will be garbage-collected.

Why does Node.js Garbage Collector not collect complied code of new Function()?

Generally, the garbage collector can and does collect compiled code, just like everything else.

Keep in mind that garbage collected systems don't free memory immediately when an object goes out of scope. At some point, the garbage collector will run again, identify unreachable objects, and free their memory.

In this particular case, it looks like DevTools are keeping extra data around (presumably for debugging purposes), which does make this look like a memory leak -- but only while DevTools are open. I've filed crbug.com/1141613 so the team can take a look.



Related Topics



Leave a reply



Submit