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 |
Chromellnode
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
JavaScript - How to Make This Code Work
Calling Method Using JavaScript Prototype
What Is the Meaning of an Underscore in JavaScript Function Parameter
Where Should Ajax Request Be Made in Flux App
JavaScript Reload the Page with Hash Value
How to Access Object Property with Invalid Characters
Javascript/Jquery Check Broken Links
Why Isn't This Object Being Passed by Reference When Assigning Something Else to It
Jquery-Ui-Dialog - How to Hook into Dialog Close Event
How to Detect Right Mouse Click + Paste Using JavaScript
How to Use Redis Publish/Subscribe with Nodejs to Notify Clients When Data Values Change
JavaScript Custom Event Listener
JavaScript Es6 Cross-Browser Detection
How to Set Image Source with Base64
Jquery, Find Div Class Name at a Certain Position While Scrolling