Javascript closures performance - javascript

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.

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.

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

Are there any benefits in using function expression in JavaScript?

I recently joined a large software developing project which uses mainly JavaScript and a particular question has been on my mind since day one. I know this issue has been here on SO before, but I have never seen the core question being properly answered. So here I ask it again:
Are there any benefits in JavaScript in using function expressions rather than function declarations?
In other words, is this:
var myFunction = function () {
// Nice code.
}
in any way better than this:
function myFunction () {
// Nice code.
}
As I see it, function expressions only introduce negative aspects on several levels to the code base. Here I list a few.
Function expression as the one above, suddenly forces you to be careful with forward references, as the anonymous function object that the myFunction variable refers to, does not exist until the variable expression actually executes. This is never a problem if you use function declarations.
Apart from generating twice as many objects as in the case with function declarations, this usage introduces a very bad programming habit, which is that developers tend to declare their functions only when they feel they need them. The result is code that mixes object declarations, function expressions and logic in something that obscures the core logic of a piece of code.
As a side effect of 2), code becomes much harder to read. If you would use proper function declarations and only var declarations for objects that actually will be variable in the code, it becomes far easier to scan the indentation line of code segment and quickly find the objects and the functions. When everything is declared as "var", you are suddenly forced to read much more carefully to find this piece of information.
As yet another nasty side effect of 2), as users get into the bad habit of only declaring their functions when they feel they need them, function expressions start showing up inside event handlers and loops, effectively creating a new copy of the function object either each time an event handler is called or for each turn in the loop. Needless to say, this is bad! Here is an example to show what I mean:
var myList = ['A', 'B', 'C'];
myList.forEach(function (element) {
// This is the problem I see.
var myInnerFunction = function () {
// Code that does something with element.
};
};
So to sum up, at least in my view, the only situation in which it is fair to use something like:
var myFunction = function () {
// Nice code.
}
is when your logic intends to change the myFunction reference to point at different functions during execution. In that situation myFunction (the variable) is something that is variable in the code, hence you are properly informing a different programmer of your intents, rather than confusing him/her.
With this background in mind, I ask my question again. Have I missed something central about function expressions (in the context described above) in which they provide any benefit over function declarations?

Most efficient alternative to making functions within a loop

The function I want to create requires an access myObject.
Is it better to create the helper function inside the main function so I have access to myObject with the scope.
Or should I make the helper function outside of myFunction and pass myObject as a parameter?
EDIT: Could I get memory-leak problem with those methods?
//Method 1
var myFunction = function(myObject){
var helper = function(i){
return console.log(i,myObject[i]);
}
for(var i in myObject){
var callback = helper(i);
}
}
//Method 2
var myFunction = function(myObject){
for(var i in myObject){
var callback = helper(i,myObject);
}
}
var helper = function(i,myObject){
return console.log(i,myObject[i]);
}
I assume you're asking for performance.
Here is a jsperf to test it for you (Yup, this exists and is very neat).
So in running the tests a bunch of times I note that neither method clearly wins. It's very close and almost certainly doesn't matter. I also note that on Windows 8.1, IE 11 blows Chrome out of the water, it's not even close - like by a factor of 20. That's a neat little result but not really indicative of real world code performance and likely we're just hitting an optimized case. Within IE the in-function version is a tiny-almost-irrelevant bit faster.
You can play with the inputs somewhat (for example I just passed in a small object, maybe a big one has different results), but I'm ready to call a preliminary conclusion: Don't worry about performance here. Use whichever one makes more sense for your specific case in terms of code clarity.
Apart from performance benefit mentioned by George Mauer, I think it will be a good idea to keep it inside to keep global context clean.
Different functions can have their own helpers defined inside them with same name rather than having function1Helper, function2Helper... in the global context.

Object Orientated Javascript / Variable declarations / Performance

So I have a rather large object orientated javascript class, with about 120 functions (a lot of getters and setters). Some of these functions have variables that are basically constants.
What I'm wondering, is should I declare these variables in a global scope of the object, so every time the function is run it doesn't have to re-declare the variable?
An example function is below. this.displayContacts is run several times (and will always run within the object), so in this case, there's no point declaring the 'codes' object inside the function?
function orderObject() {
this.displayContacts = function() {
var codes = {'02':'02','03':'03','07':'07','08':'08'};
// do something with codes
};
}
So, would this be better, performance wise?
function orderObject() {
var codes = {'02':'02','03':'03','07':'07','08':'08'};
this.displayContacts = function() {
// do something with codes.
};
}
My other concern is that if I end up with a lot of global variables/objects inside the main orderObject, will that be MORE of a performance hit than simply re-declaring the variables each time?
absolutely.
function MyClass() {
this.somevar = ''; // instance scoped variable
};
MyClass.CODES = {'02':'02'...}; // 'Class' scoped variable; one instance for all objects
MyClass.prototype.instanceMethod = function(){
// 'this' refers to the object *instance*
// it can still use MyClass.CODES, but can also account for variables local to the class
}
CONSTANT is 'static' so to speak, in java-talk. If your codes are global to the class (and the rest of your application), you will save a lot of overhead this way -- only define the object once. Note that you can have 'static' class-level methods as well, for those cases where the function doesn't need to operate on variables specific to an instance of the class.
Unless your app is really beefy, performance optimization probably wont make it noticeably faster. But that doesn't mean that OO design is not worth-while -- if you are going to use javascript in an object oriented way, its not too hard and never a bad idea to use good OO principals.
I would say that if you have something that you are using in multiple places that it should become a property of your object so that it doesn't have to be redeclared each time. It would also help make the maintenance of the object easier if that constant has to change. Then you are changing it only in one place and not having to hunt down all the locations where you used it.
Don't repeat yourself.
Garbage collection in JavaScript depends on the browser, and most modern browsers handle it pretty well. If you go ahead and make these global, you might see a slight performance increase simply because it's not executing that line of code every time. However, I can't imagine any significant increase in performance by making these static properties on the class, but if they don't change, then it would make more sense.

Categories

Resources