function(foo, cb) {
var bigObject = new BigObject();
doFoo(foo, function(e) {
if (e.type === bigObject.type) {
cb();
// bigObject = null;
}
});
}
The above example shows a classic, accidental (or maybe not) memory-leaking closure. The V8 garbage collector can't determine if it's safe to remove the bigObject
because it's being used in the callback function which can be called several times.
One solution is to set bigObject
to null
when the job in the callback function is over. But if you are using many variables (imagine there is n
variables like bigObject
, and they are all used in callback) then cleaning this becomes an ugly problem.
My question is this: is there any other way to clean those used variables?
EDIT Here's another (real world) example: So I get application from mongodb and compare it to some other application. Callback from mongodb uses variable application that is defined out of that callback. After I get result from mongodb I return it also as a callback (because it is all async and I cant just write return ). So actually it can happen that i propagate callback all the way to the source...
function compareApplications(application, condition, callback) {
var model = database.getModel('Application');
model.find(condition, function (err, applicationFromMongo) {
var result = (applicationFromMongo.applicationID == application.applicationID)
callback(result)
}
}
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.
Only capture variables as unowned when you can be sure they will be in memory whenever the closure is run, not just because you don't want to work with an optional self . This will help you prevent memory leaks in Swift closures, leading to better app performance.
Memory leaks can and do happen in garbage collected languages such as JavaScript. These can go unnoticed for some time, and eventually they will wreak havoc. For this reason, memory profiling tools are essential for finding memory leaks.
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.
If your callback function is only supposed to be called once, then you should unsubscribe after it is called. That will release your callback + closure to the GC. With your closure released, bigObject
will also be free to be collected by the GC.
That's the best solution - as you noted, the GC doesn't magically know your callback will only be called once.
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