javascript interval memory leak - javascript

I am reading this article on javascript optimization. Article
I came across this section and it tells me when a leak occurs. But I can't find what is the proper way to call it so a leak does not occur. Here is the section I am interested in.
One of the worst places to leak is in a loop, or in setTimeout()/setInterval(), but this is quite common.
Consider the following example.
var myObj = {
callMeMaybe: function () {
var myRef = this;
var val = setTimeout(function () {
console.log('Time is running out!');
myRef.callMeMaybe();
}, 1000);
}
};
If we then run:
myObj.callMeMaybe();
to begin the timer, we can see every second “Time is running out!” If we then run:
myObj = null;
The timer will still fire. myObj won’t be garbage collected as the closure passed to setTimeout has to be kept alive in order to be executed. In turn, it holds references to myObj as it captures myRef. This would be the same if we’d passed the closure to any other function, keeping references to it.
It is also worth keeping in mind that references inside a setTimeout/setInterval call, such as functions, will need to execute and complete before they can be garbage collected.
The question is: How do you do this properly so that you don't leak? Is it as simple as calling clearInterval? And does this leak once or leak once per interval

I wouldn't call this a memory leak in any fashion - it's simple garbage collection doing what it's supposed to. There is no more "proper" way to do it.
The object that was initially pointed to by myObj is still in use as long as your timer is running. A garbage collector will free it as soon as there are no more references to it. Setting myObj = null clears one reference to it, but your ongoing timers have another reference in myRef so it can not be garbage collected until ALL references to it are gone.
Yes, if you stop your timer and set myObj = null, then there will be no more references to the object and the GC will get rid of it. Keep in mind that you will need to provide access to the timerid if you want to stop the timer from the outside because no outside code can get to val where you have it stored now.
If you had lots of other data in myObj that the timer did not need access to and you were trying to allow that data to be freed while the timer continues to run, then you can either keep the same structure you have now, but clear that other data from the object (either remove the properties or set the properties to null) or you can change the structure of your code so that the recurring timer is launched with a separate function call and doesn't have to keep a reference to the object in order to call a method.
In other words, if your timer method needs access to the object, then the object is correctly kept alive by the garbage collector. If the timer method doesn't need access to the object, then you should run the recurring timer some other way that doesn't repeatedly call a method on the object - allowing the object to be garbage collected.

Related

Closure memory leak of unused variables

I'd like to understand under which circumstances variables which are no further used are stored in closures and lead to memory leaks. My most preferred outcome would be "there are none", but this doesn't seem to be the case.
From what I understand, once a function is declared inside another function, its internal [[scope]] is assigned the LexicalEnvironment of its encapsulating function. This LexicalEnvironment has reference local variables and the entire scope chain at that point. This basically includes all free variables the function could access (from what I understood of lostechies, javascript closures explained).
Here the first issue arises: this should mean all those variables can be reached as long as the function lives. E.g. the following should already leak:
function a() {
let big = new Array(1000000).join('*'); //never accessed
//function unused() { big; }
return () => void 0;
}
let fstore = [];
function doesThisLeak() {
for(let i = 0; i < 100; i++) fstore.push(a());
}
doesThisLeak();
This luckily doesn't seem to be the case on my firefox. I've received several explanations to why this doesn't leak, from "the jitter is smart" to "LexicalEnvironment is a record type which means GC can collect the unused variables". I still don't know whether either is correct, whether this doesn't leak on all modern runtimes and why.
After further research, I found auth0, four types of leaks in javascript (sadly, there appears to be no html id to jump to, the relevant part is "4: Closures") which shows a way to trick whatever smart thing is collecting the unused variables. In above snippet, when just uncommenting the "unused" function, I do not see RAM usage ever going down again (it was already noted that it could be GC simply did not run for other reasons. However, so far, I am assuming it leaks. I also got told this was limited to firefox, but it appeared to produce similar behavior in chrome)
This example (in case it really does what i believe it does), shows that completely unused variables can leak due to a function declaration in the same scope.
To conclude my problems:
What is the reason for, in the above snippet, "big" getting collected (when "unused" is commented) and does this happen on all modern runtimes?
Assuming the example with the "unused" function not commented leaks, what are best practices to avoid such accidental leaks? Are there any more? I already got the suggestion of null'ing all local variables which are not further used at the end of functions, however, this seems absurdly ugly. I fear using temporary variables for pre-calculations and accidentally leaking.
PS: It is quite hard to make certain that this question has not already been asked in the jungle of questions about memory leaks with closures.
The compiler can examine the code of the returned function to see which free variables it references, and only those variables need to be saved in the closure, not the entire LexicalEnvironment. You can see this by examining the closure in the Javascript debugger.
function a() {
let big = new Array(1000000).join('*');
let small = "abc"; // is accessed
return (x) => small + x;
}
fun = a();
console.dir(fun);
function b() {
let big = "pretend this is a really long string";
function unused() { big; }
return () => void 0;
}
fun = b();
console.dir(fun);
When you expand the first function in the debugger, you'll see small in the Closure property, but not big. Unfortunately, the Chrome compiler doesn't seem to be clever enough to detect when the variable is referenced in an unused function that isn't returned, so it doesn't need to be saved, so we get a leak in b().
Any data that isn't saved in the closure becomes garbage and can be collected, so it won't leak.
After you call a() your fstore has reference to created function () => void only. After a() returns, its scope vars will be deleted. It means that no vars has reference to your new Array(1000000).join('*') and it will be garbage collected. It will be collected the same way if you uncomment unused function because it will deleted too. There are no leaks in your code.
pic1
You can think about Javascript scope chain with the problem.Identify a Function will create a new scope chain.If function's local scope do not have a local variable, it will reference to outside scope of lexical environment, it will keep over in the memory
here's a link

Referencing parent scope in function, probability of leak?

When referencing a parent variable in a setInterval, do this can provoke a leak as I'm referencing self ?
var A = {};
A.act = function(a_var) {
var self = this;
self.a_var = a_var;
setInterval(function() {
console.log(self.a_var);
}, 100)
}
A.act();
Well, there's a leak in the sense that you start an interval timer running that you cannot stop without leaving the page (since you don't keep the handle). That means that the context of the call to act that created the timer, the timer callback, and A can never be GC'd, because the browser has a reference to the callback in its timer list, and the callback closes over the context of the call that created it. But I'm assuming that's desired behavior, so not really a leak.
In theory, the a_var argument is referenced by the closure (indirectly, by referencing the binding object of the execution context of the call to act), and so sticks around in memory even though you don't use it (you use self.a_var instead).
In practice (which is to say, allowing for implementation optimizations), it's complicated. Modern engines can optimize out variables and such that they know a closure doesn't access, but surprisingly simple things can disturb that process (at least on V8). This other question and answer have more on that.

Javascript delete statement

Q: I am trying to work out why there is a delete statement in this code?
My assumption is foo will be dereferenced once statement has finished executing therefore would be no need to explicitly do it.
(function () {
var foo = globalObject;
foo.bar = function () {
//code here
}
delete foo;
}());
What is going on here?
See this article on when To and Not To use the delete operator.
This does not appear to be a proper use.
Local variables cannot be deleted as they are marked internally with the DontDelete attribute. There are occasions when you might want to clear a local variable (if you want to release any memory used by it and the scope may survive indefinitely in a closure), but you don't use the delete operator for this purpose - you can just set it to null.
In normal functions that don't create closures, any local variables will simply be garbage collected when the function completes and if there are no other references to their data in other code, that data will be freed by the garbage collector.
The only time you need to worry about clearing references to data is when you have a scope that will exist for a long duration of time (closure or global) and you no longer need that data and it's useful to free up its memory usage.
FYI, the most common use of the delete operator is to remove a property from an object as in:
var foo = {x: 1, y: 2};
delete foo.x;

Memory leakage on event handling

I've been reading about memory leakages lately and haven't yet wrapped my head around all of it and have some questions regarding my own style of writing. Specifically, I'm not really sure if the way I handle events might be a source of leaking. Consider the following code
function Wrapper(text) {
this.text = text;
this.bindHandlers();
};
Wrapper.prototype.onClick = function (e) {
alert(this.text);
};
Wrapper.prototype.bindHandlers = function () {
var t = this, div = $('<div>' + this.text + '</div>');
var reallyHugeArray = [1,2,3...]; // an array of 100000 elements for example
div.click(function (e) {
// all variables of the parent function are in scope for this function, including reallyHugeArray
t.onClick(e);
});
$(document).append(div);
};
var a = new Wrapper('testString');
// had enough fun with the Wrapper, now let's nullify it
a = null;
As you can see, I like to use an anonymous functions as the event handler so that it would be more convenient to have access to instance specific variables (in this case this.text in the onClick function) and functions. However, if I understood correctly, having an anonymous function inside a function (as is the event handler), which has access to the local scope, disables the garbage collector from removing the local variables, therefore creating a leak.
So my question is whether this method of event handling can create memory leakages and if it does, is there any way to prevent it, but still have a similarily convenient way to access the instance variables and functions?
(Off-topic: a function inside a function inside a function makes Javascript sound like Inception)
In your particular example, the anonymous click handler creates a function closure for the scope above it. That means that the values of t, div and reallyHugeArray are maintained for the life of your anonymous click handler function.
This is not a really a memory "leak", but rather memory "usage". It doesn't get worse and worse over time, it just uses the fixed amount of memory that those local varaibles t, div and reallyHugeArray occupy. This is often an advantage in javascript programming because those variables are available to the inner function. But, as you wondered, it can occasionally cause problems if you expected that memory to be freed.
In the case of references to other things (DOM objects or other JS variables), since these outer variables continue on, everything that they refer to also continues on and cannot be freed by the garbage collector. In general, this is not a big problem. Things that tend to cause problems are things that are done over and over as the web page is used or things that are done in some large loop with lots of iterations. Something only executed once like this just uses a little more memory once and from then on the memory usage of the construct is constant.
If, for some reason, you were binding this event handler over and over again, creating a new function closure every time and never releasing them, then it could be a problem.
I find this construct in Javascript very useful. I don't think of it as something to stay away from, but it is worth understanding in case you have references to really large things that you want to be freed, transient things that should be freed because you don't need them long term or you're doing something over and over again. In that case, you can explicitly set local variables to null if you won't need them in the inner function to kill their references and allow the garbage collector to do it's thing. But, this is not something you generally need to do - just something to be aware of in certain circumstances.

Self destructing Javascript function - How does it work?

So I found this piece of code and it obviously works (as it has been in production for years):
window[someMethod] = function (tmp) {
callback({prop:"val"}, tmp);
// Garbage collect
window[someMethod] = undefined;
try {
delete window[someMethod];
}
catch (e) { }
if (head) {
head.removeChild(script);
}
// head refers to DOM head elem and script refers to some script file elem
};
Curious to know, how does it work?
How can it set itself to undefined within its body and try to
delete itself?
Does the browser know to not execute the undefined and delete until the call is finished? And how?
If the browser deletes it right away, then what happens after? Does the last line run?
Finally, do you guys see this leaking memory? If yes, how?
It's not setting itself to undefined, it's setting a reference to itself to undefined. If you think of a function as a block of code in memory, that block of code isn't deleted in this case, just the reference to it. You never explicitly delete anything in JavaScript, you simply remove references to it and leave it to the garbage collector to clean up. Note, this might not be the case for actual code, just heap objects, as its up to the engine how to treat it (interpret it, compile it, execute it on an abacus, whatever)
Based on that logic, once the function is executing, the original reference to it is no longer required as it was needed only initially to transfer execution to it.
You're misunderstanding JS evaluation as requiring a reference to it for every statement. In all likelihood, this method has been Just-In-Time compiled and is now executing just like any other non-JS function would run.
There are no apparent memory leaks in the code above.
Hopefully this is making sense.
Remember you can't ever explicitly delete something in Javascript. All you can do is remove all the references to it and so let the garbage collector remove it on the next cycle. By the end of this function, the function itself is still in memory, but there are no external references to it. Next time the GC runs, it will spot this and deallocate its memory.
window[someMethod] is simply a reference. Only the reference is deleted, not the function itself.
Once the function is done, and all reference to it are removed, garbage collection should take care of it, avoiding memory leaks.

Categories

Resources