Garbage Collection with Node.Js

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();
}

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.

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.

Node.js stream pipes and garbage collection

The answer, as usual, is: it depends.

If nothing references the stream objects then they will be garbage collected. However, there might be references elsewhere than in your code.

Note that the writable stream is referenced by the readable stream via event handlers, so all we really need is a reference to the readable stream to keep both alive.

If the source is a stream that is capable of producing data all by itself (it reads from a file, the network, or something in memory) and the pipeline is flowing, then it will be referenced by a callback somewhere (an I/O continuation, event handler, or closure given to setTimeout() or process.nextTick()).

If the source is a stream that is waiting for you to push data into it or the pipeline is paused, then there are likely no references and both streams will eventually be garbage-collected.

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



Related Topics



Leave a reply



Submit