Javascript variables and memory leaking? - javascript

Is it possible to create memory leaks when coding in Javascript? and if so is this dependent on the Javascript rendering engine e.g. V8 or IE's Chakra
I seem to be getting really slow performance when iterating through large loop constructs.
Should i "delete" the variables that im not using?
var myVar = 'very very long string';
delete myVar;

In the example you've shown, unless myVar is in the global scope it will simply be garbage collected at the end of the function.
In general, you don't need to worry about memory in JavaScript. Where you do need to worry about memory is when you unintentionally create references to objects and forget about them. For example:
function buttonClick() {
var clicked = false;
document.body.addEventListener('click', function(event) {
if (clicked) return;
if (event.target.nodeName !== 'button') return;
clicked = foo();
}, true);
}
The above code is bad code to begin with (not cleaning up event listeners), but it illustrates the example of a "memory leak" in JavaScript. When buttonClick() is called, it binds a function to the click event on the <body>. Because removeEventListener is never called to unbind the listener, the memory used by the function is never reclaimed. That means that every time buttonClick() is called, a little bit of memory will "leak".
Even then, however, the amount of memory leaked is quite small and won't ever become a problem for the vast majority of use cases. Where it would likely be a problem is in server-side JavaScript, where the code is potentially run much more frequently and the process stays alive for much longer.

Related

JavaScript experts: Do block-scopes with `{}` and anonymous functions both help garbage-collection?

In the book "You don't know JS: scopes & closures", Kyle simpson states that a block-scoped variable helps with garbage collection, here is the specific example:
function process(data) {
// do something interesting
}
{
let someReallyBigData = {};
process(someReallyBigData);
}
var btn = document.getElementById("my_button");
btn.addEventListener("click", function click(evt) {
console.log("Clicked!");
}, false);
Now the above example is supposed to help with garbage-collection since the variable someReallyBigData will be dropped from memory as soon as the block ends, unlike this example, which doesn't help with garbage-collection:
function process(data) {
// do something interesting
}
var someReallyBigData = {};
process(someReallyBigData);
var btn = document.getElementById("my_button");
btn.addEventListener("click", function click(evt) {
console.log("Clicked!");
}, false);
Now I am sure this guy is correct about the examples he provided (the first one); however, i am wondering whether or not everything would be the same if we used an anonymous IIFE (Immediately Invoked Function Expression) along with a normal var instead of the {} curly braces and the let variable. Let me turn that into an example:
function process(data) {
// do something interesting
}
(function(){
var someReallyBigData = {};
process(someReallyBigData);
}());
var btn = document.getElementById("my_button");
btn.addEventListener("click", function click(evt) {
console.log("Clicked!");
}, false);
Looking at it from the surface, they both should do the same thing; since just as the block-scoped someReallyBigData variable could not be accessed anymore by anything after the block of code had executed, the code inside the anonymous function cannot be accessed by anything once it has executed, by anything, from anywhere.
So, do they really have the same effect on the garbage-collection mechanisms of the Javascript engine ? I was almost certain this was the case until I googled "anonymous function garbage-collection" and almost all the material that showed up said only negative things like "anonymous functions cause memory leaks" and etc.
I would be glad if someone could shed some light on this thing.
Please don't forget that my question is a bit specific to the examples I provided, thanks!
(V8 developer here.) Yes, there are several ways to make objects unreachable, including at least all of the following:
Put stuff in let-declared variables in a block scope
Put stuff into an IIFE
Clear the variable (var or let) when you're done with it: someReallyBigData = null;
The end result will be the same in all cases: objects that are no longer reachable are eligible for garbage collection.
Other notes based on the discussion here:
The advice quoted in the question makes sense for top-level code. Within a reasonably sized function, I wouldn't worry about it -- the function will probably return soon enough that there is no difference, so you don't need to burden yourself with such considerations.
There's a big difference between "an object can be freed now" and "an object will be freed now". Letting something go out of scope does not cause it to be freed immediately, and does not cause the garbage collector to run more often. It just means that whenever the garbage collector next decides to go looking for garbage, the object in question will be eligible.
IIFEs are IIFEs regardless of whether they're anonymous or not. Example:
(function I_have_a_name() {
var someReallyBigData = ...;
})();
// someReallyBigData can be collected now.
I_have_a_name(); // ReferenceError: I_have_a_name is not defined
Creating closures in and of itself does not keep things alive. However, if closures reference variables in their outer scope, then (of course!) those can't be collected as long as the closure is around. Example:
var closure = (function() {
var big_data_1 = ...;
var big_data_2 = ...;
return function() { return big_data_1.foo; }
})();
// big_data_2 can be collected at this point.
closure(); // This needs big_data_1.
// big_data_1 still cannot be collected, closure might need it again.
closure = null;
// big_data_1 can be collected now.
The optimizing compiler has little influence on all this. It usually operates on a per-function bases, and usually the top-level is not optimized (because most logic tends to be in functions). Within a function, the optimizing compiler is very well aware of the lifetimes of objects (that's part of what it means to be an optimizing compiler).
JavaScript only has block level scope when you use the let or const keywords in declarations. Just because you have {} alone does not create block-level scope (as is the case in most other languages).
Aside from that, garbage collection is implementation dependent and you would most likely not notice any difference in performance due to block scoping.
Anonymous functions can have an impact on garbage collection because the function can be set up in such a way that it doesn't have to be stored for potential calling later. A good example of this would be a function that needs to run only once (i.e. when the document is fully parsed):
window.addEventListener("DOMContentLoaded", function(){ . . . });
However, that doesn't mean that all anonymous functions provide this benefit because the function could wind up being stored (i.e. if it is returned from a function and then captured in a variable) or if the anonymous function sets up closures, then all bets are off.
Also, be aware that you can't unit test anonymous functions as simply as you can named functions.
I am wondering whether or not everything would be the same if we used an anonymous IIFE
Sure that's possible, it's what transpilers do to emulate block scopes as well. However IIFEs look a bit awkward, block scopes with let/const variables are easier to use. See also Will const and let make the IIFE pattern unnecessary?.
Now the first example is supposed to help with garbage-collection since the variable someReallyBigData will be dropped from memory as soon as the block ends, unlike the second example, which doesn't help with garbage-collection.
Notice that the word is helps, not enables. Today's engines can garbage-collect the variable just fine, as their optimiser sees that it's not used in the preserved closure. The block scope only makes this kind of static analysis easier.

Javascript closures performance

I have being working for a while in javascript and usually do something like this just to cache the value of properties of functions that are declared inside a deep structure or "namespace"
//global scope
(function ($, lib) {
//function scope 1
var format = lib.format, // instead of calling lib.format all the time just call format
touch = lib.pointer.touch, //instead of calling lib.pointer.touch each time just touch
$doc = $(document),
log = logger.log; //not console log...
$doc.on('app:ready', function () {
//function scope 2
$doc.on('some:event', function (e) {
//function scope 3
//use the cached variables
log(format('{0} was triggered on the $doc object', e.type);
});
$doc.on(touch, function (e) {
//function scope 3
log(format('this should be {1} and is... {0} ', e.type, touch);
});
});
}(jQuery, lib));
I was doing that because:
as lazy as I am, writing touch seem more appealing that writing lib.pointer.touch, even when powerful IDEs with fancy autocompletion could help on this, touch is shorter.
a minimizer could convert that single private variable to a single letter variable, so it also made sense for me (I know, I know, never optimize too soon, but this seems to be safe I guess)
All the code written that way seems to perform decently on mobile devices and desktop browsers, so It seems to be a safe practice (In "the practice", pun intended). But I since this relies in closures, and inner functions have to create a closure to save the context it was declared I was wondering...
if a function does not uses variables from the outside context (free variables)... is the closure context still saved? (or if i a tree falls in the wood and nobody is there to hear it, does it still make the crash sound? hehe) I'm aware that this could vary between javascript engines, because ECMA mention nothing about if it is required to save the context or not when variables from the outside are not accessed.
if the above expression is true... will this block of code be more efficient?
//global scope
(function ($, lib) {
//function scope 1
var format = lib.format,
touch = lib.pointer.touch,
$doc = $(document),
log = console.log;
$doc.on('app:ready', function () {
(function ($doc, touch, lib, format) {
// since all the variables are provided as arguments in this function
// there is no need to save them to the [[scope]] of this function
// because they are local to this self invoking function now
$doc.on('some:event', function (e) {
//function scope 3
//use the cached variables
log(format('{0} was triggered on the $doc object', e.type);
});
$doc.on(touch, function (e) {
//function scope 3
log(format('this should be {1} and is... {0} ', e.type, touch);
});
}($doc, touch, lib, format));
});
}(jQuery, lib));
Is it more efficient because it passes those variables to self immediate invoking function? will the cost of creating that new function any impact in the code, (negative or positive)?
How I can properly measure the memory consumption of my javascript library in a reliable way? I have 100x little javascript modules all inside immediate self invoking functions mostly to avoid variables from leaking to the global context. So They all are wrapped in modules very similar to the block of code mentioned above.
will it have a better effect to cache the variables closer, even when that will mean I will have to repeat the declarations of the variables closer to where they're going to be used?
I have the feeling that looking for a variable not in the current local context, the engine will first look into the parent scope and iterate over all the variables at that level... the more variables per level, worse would probably be the performance looking for a variable.
try to find an undefined variable from the internal closures will be the most expensive, because by definition the variable will be first search on the parent scope until the global scope, and not finding it will force the engine to finally reach the global scope. Is that true? are engines optimizing this kind of lookups?
In the end... I know that I will not want to implement my code as the second example mostly because It will make the code harder to read and I'm kinda confortable with the minimized size of the final output using the first approach. My question is motivated by the curiosity and to try to understand a bit better this really nice feature of javascript.
Accordingly to this test...
http://jsperf.com/closures-js
It seems the second approach is faster. But is only evident when iterating an insane number of times... Right now my code does not do that number of iterations... but probably is consuming more memory because of my way of coding...
update: it has being pointed to me that this question is too large. I'm sorry will try to break in small parts. This question was motivated mostly by curiosity as I said, performance seems negligible even in mobile devices. Thank you for all your feedback.
I think it is premature optimization. You already know performance is not a problem in most cases. Even in tight loops, performance does not degrade that bad. Let the JavaScript engine optimize this on its own as Chrome has started doing, by removing unneeded variables from closures.
One important thing is, don't make your code harder to read with unnecessary optimization. Your example takes quite a bit more code, hampering development. In some cases, we are forced to make the code harder to read because we know a particular piece of the app is more memory/performance intensive, but only at that point should we do that.
If you add a breakpoint to the following code (in Chrome), you'll see that the world variable has been optimized out of the closure, look at the 'Closure' node under the Scope Variables http://jsfiddle.net/4J6JP/1/
.
(function(){
var hello = "hello", world="world";
setTimeout(function(){
debugger;
console.log(hello);
});
})()
Note that if you add an eval in that inner function, then all bets are off and the closure can't be optimized.

Does the js event-loop mean you can use global variables for temp scratch-space?

* Disclaimer: I'm not saying this is a good idea - as a matter of fact I'll explicitly say it is not - so take this question by way of trying to understand what exactly the event-loop means for coding style.
My rudimentary understanding of the javascript-has-no-threads mantra is that the runtime treats all of javascript as short "blocks of code" which are scheduled executed one after the other without ever shifting away from a block during execution. A block of code (I don't know the real terminology) in this case is basically code that runs as a result of an event handler being triggered.
If my understanding is correct that would mean that it is technically 100% safe to use global variables if your use of them does not span more than one "block of code".
So for example if I have a single global object window.workspace I could have my event handlers and any code that flows from there - rather than storing temporary variables in closures - store them all in window.workspace. As long as I don't assume that workspace to retain any state in between calls to event handlers (even the same one), this should be perfectly safe.
Is this accurate (though, once again, not advised)
Exactly how a JavaScript event mechanism works is up to the container in which JavaScript runs. It would be possible to set up a system wherein event handlers always had some sort of persistent state object passed in on each call.
In browsers and systems like Node.js, however, the answer to your question (to the extent I understand it) is a guarded "yes", or maybe "yes but".
Because JavaScript has closures, a cleaner way to ensure that there's persistent (not like DB persistence; I mean persistent across invocations of an event handler) but private storage is to do something like this:
(function(global) {
var persistentValue = 12;
// set up an event handler
global.whatever().handleEvent(function() {
if (persistentValue > 12) { ... }
else { persistentValue ++; }
});
})( this );
The idea is that the "persistentValue" variable remains "alive" in the closure around the event handler, so each time it's called it'll see that variable as it was the last time it ran. Now, of course if other event handlers are created in the same wrapper function, then they'll also have access to the variable. In that sense, it's like a relatively-global variable to those handlers.

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