In trying to debug memory leaks in NodeJS, I'm finding it quite difficult (given the lack of profiling tools that I am aware of).
I thought I'd go back to basics and make sure I understand how a memory leak would be created specifically in NodeJS. I'm confused about the types of closures that might cause memory leaks and am unsure of what the garbage collector needs in order to free up that memory.
Could you give me some examples of basic patterns that would cause a memory leak in Node.js?
In simple terms, a closure is an inner function that has access to the outer function's scope. In the example above, largeArray is never returned and cannot be reached by garbage collector, significantly increasing its size through repeated calls of inner functions, resulting in a memory leak.
Closures, timers, and event handlers can often create memory leaks in Node. js applications. Let's look at a piece of code from the Meteor team explaining a closure that leads to a memory leak. It leads to a memory leak as the longStr variable is never collected and keeps growing in memory.
This process of accessing outer function's variable by an inner function is called a closure. A memory leak occurs when a declared variable is automatically available to the inner nested function and resides in a memory despite it is not referenced in the inner nested function.
Not a "leak" exactly, but this can be a common pitfall.
var fn = (function() {
var a = "super long string ...";
var b = "useless value";
var c = "Hello, World!";
return function() {
return c;
};
})();
This returns a function that references a scope, and every single local var in that scope will be kept, even though only one of those values are needed. This results in more memory usage than you need, especially if your function uses a small variable, but there are large values in that scope that you dont need to keep referencing.
How to fix it?
Simple option is to null out the variables you dont care about at the end of your function. The variables are still in scope, but their data would be released.
var fn = (function() {
var a = "super long string ...";
var b = "useless value";
var c = "Hello, World!";
// do stuff with a and b
a = b = null;
return function() {
return c;
};
})();
Or you could break anything that uses temp vars into it's own function so their scopes can be released. This is a better solution for a larger project.
var doSetup = function() {
var a = "super long string ...";
var b = "useless value";
// do stuff with a and b
};
var fn = (function() {
doSetup();
var c = "Hello, World!";
return function() {
return c;
};
})();
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