We know node.js provides us with great power but with great power comes great responsibility.
As far as I know the V8 engine doesn't do any garbage collection. So what are the most common mistakes we should avoid to ensure that no memory is leaking from my node server.
EDIT: Sorry for my ignorance, V8 does have a powerful garbage collector.
Avoid Accidental Globals This could be the result of a typo and could lead to a memory leak. Another way could be when assigning a variable to this within a function in the global scope. To avoid issues like this, always write JavaScript in strict mode using the 'use strict'; annotation at the top of your JS file.
Finding the leak. Chrome DevTools is a great tool that can be used to diagnose memory leaks in Node. js applications via remote debugging. Other tools exist and they will give you the similar.
As far as I know the V8 engine doesn't do any garbage collection.
V8 has a powerful and intelligent garbage collector in build.
Your main problem is not understanding how closures maintain a reference to scope and context of outer functions. This means there are various ways you can create circular references or otherwise create variables that just do not get cleaned up.
This is because your code is ambigious and the compiler can not tell if it is safe to garbage collect it.
A way to force the GC to pick up data is to null your variables.
function(foo, cb) { var bigObject = new BigObject(); doFoo(foo).on("change", function(e) { if (e.type === bigObject.type) { cb(); // bigObject = null; } }); }
How does v8 know whether it is safe to garbage collect big object when it's in an event handler? It doesn't so you need to tell it it's no longer used by setting the variable to null.
Various articles to read:
I wanted to convince myself of the accepted answer, specifically:
not understanding how closures maintain a reference to scope and context of outer functions.
So I wrote the following code to demonstrate how variables can fail to be cleaned up, which people may find of interest.
If you have watch -n 0.2 'ps -o rss $(pgrep node)'
running in another terminal you can watch the leak occurring. Note how commenting in either the buffer = null
or using nextTick
will allow the process to complete:
(function () { "use strict"; var fs = require('fs'), iterations = 0, work = function (callback) { var buffer = '', i; console.log('Work ' + iterations); for (i = 0; i < 50; i += 1) { buffer += fs.readFileSync('/usr/share/dict/words'); } iterations += 1; if (iterations < 100) { // buffer = null; // process.nextTick(function () { work(callback); // }); } else { callback(); } }; work(function () { console.log('Done'); }); }());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With