obj = [1,2,3,4,5];
function iter(){
for (var key in obj){
key=key+key;
};
};
function test1() {
iter(obj);
};
function test2(){
(function iter(obj){
for (var key in obj){
key=key+key;
};
})(obj);
};
Here, both test1 and test2 perform the same, even though test2 is supposedly creating a new function everytime it is called. Why?
My guess is that there's no difference in performance because there's no (meaningful) difference in the code. The parser creates the local iter function inside test2 once when it parses the code, not each time test2 is called. (This isn't like using eval.) If anything, the second one will be a tiny bit faster because obj is local to the iter function. Well, that was wrong.
As this jsperf test shows, the second is indeed slower. You have to be careful about measurement. The way you wrote the functions, the amount of work being done in the function bodies easily masks the difference in function call overhead involved in the two cases. Also, the first case is accessing a global obj, while the second is accessing an argument. These differences should be eliminated to, as much as possible, measure only what you're trying to measure. The jsperf test I wrote tries to do just that.
I would pretty much guarantee that you will not see the performance difference in only 5 cycles. In modern JS engines, you will need to test this with iterations in the thousand or even tens of thousands range to actually see the difference. However, that difference will most certainly show up eventually.
Your are right, they do more or less perform the same
Your second function, which has a closure in it, has the overhead of creating an anonymous function every time it is called.
In the first one, js can call the function it has already stored.
That leads to the second function being a tiny bit slower.
Related
I'm kind of curious about what the best practice is when referencing the 'global' namespace in javascript, which is merely a shortcut to the window object (or vice versia depending on how you look at it).
I want to know if:
var answer = Math.floor(value);
is better or worse than:
var answer = window.Math.floor(value);
Is one better or worse, even slightly, for performance, resource usage, or compatibility?
Does one have a slighter higher cost? (Something like an extra pointer or something)
Edit note: While I am a readability over performance nazi in most situations, in this case I am ignoring the differences in readability to focus solely on performance.
First of all, never compare things like these for performance reasons. Math.round is obviously easier on the eyes than window.Math.round, and you wouldn't see a noticeable performance increase by using one or the other. So don't obfuscate your code for very slight performance increases.
However, if you're just curious about which one is faster... I'm not sure how the global scope is looked up "under the hood", but I would guess that accessing window is just the same as accessing Math (window and Math live on the same level, as evidenced by window.window.window.Math.round working). Thus, accessing window.Math would be slower.
Also, the way variables are looked up, you would see a performance increase by doing var round = Math.round; and calling round(1.23), since all names are first looked up in the current local scope, then the scope above the current one, and so on, all the way up to the global scope. Every scope level adds a very slight overhead.
But again, don't do these optimizations unless you're sure they will make a noticeable difference. Readable, understandable code is important for it to work the way it should, now and in the future.
Here's a full profiling using Firebug:
<!DOCTYPE html>
<html>
<head>
<title>Benchmark scope lookup</title>
</head>
<body>
<script>
function bench_window_Math_round() {
for (var i = 0; i < 100000; i++) {
window.Math.round(1.23);
}
}
function bench_Math_round() {
for (var i = 0; i < 100000; i++) {
Math.round(1.23);
}
}
function bench_round() {
for (var i = 0, round = Math.round; i < 100000; i++) {
round(1.23);
}
}
console.log('Profiling will begin in 3 seconds...');
setTimeout(function () {
console.profile();
for (var i = 0; i < 10; i++) {
bench_window_Math_round();
bench_Math_round();
bench_round();
}
console.profileEnd();
}, 3000);
</script>
</body>
</html>
My results:
Time shows total for 100,000 * 10 calls, Avg/Min/Max show time for 100,000 calls.
Calls Percent Own Time Time Avg Min Max
bench_window_Math_round
10 86.36% 1114.73ms 1114.73ms 111.473ms 110.827ms 114.018ms
bench_Math_round
10 8.21% 106.04ms 106.04ms 10.604ms 10.252ms 13.446ms
bench_round
10 5.43% 70.08ms 70.08ms 7.008ms 6.884ms 7.092ms
As you can see, window.Math is a really bad idea. I guess accessing the global window object adds additional overhead. However, the difference between accessing the Math object from the global scope, and just accessing a local variable with a reference to the Math.round function isn't very great... Keep in mind that this is 100,000 calls, and the difference is only 3.6ms. Even with one million calls you'd only see a 36ms difference.
Things to think about with the above profiling code:
The functions are actually looked up from another scope, which adds overhead (barely noticable though, I tried importing the functions into the anonymous function).
The actual Math.round function adds overhead (I'm guessing about 6ms in 100,000 calls).
This can be an interest question if you want to know how the Scope Chain and the Identifier Resolution process works.
The scope chain is a list of objects that are searched when evaluating an identifier, those objects are not accessible by code, only its properties (identifiers) can be accessed.
At first, in global code, the scope chain is created and initialised to contain only the global object.
The subsequent objects in the chain are created when you enter in function execution context and by the with statement and catch clause, both also introduce objects into the chain.
For example:
// global code
var var1 = 1, var2 = 2;
(function () { // one
var var3 = 3;
(function () { // two
var var4 = 4;
with ({var5: 5}) { // three
alert(var1);
}
})();
})();
In the above code, the scope chain will contain different objects in different levels, for example, at the lowest level, within the with statement, if you use the var1 or var2 variables, the scope chain will contain 4 objects that will be needed to inspect in order to get that identifier: the one introduced by the with statement, the two functions, and finally the global object.
You also need to know that window is just a property that exists in the global object and it points to the global object itself. window is introduced by browsers, and in other environments often it isn't available.
In conclusion, when you use window, since it is just an identifier (is not a reserved word or anything like that) and it needs to pass all the resolution process in order to get the global object, window.Math needs an additional step that is made by the dot (.) property accessor.
JS performance differs widely from browser to browser.
My advice: benchmark it. Just put it in a for loop, let it run a few million times, and time it.... see what you get. Be sure to share your results!
(As you've said) Math.floor will probably just be a shortcut for window.Math (as window is a Javascript global object) in most Javascript implementations such as V8.
Spidermonkey and V8 will be so heavily optimised for common usage that it shouldn't be a concern.
For readability my preference would be to use Math.floor, the difference in speed will be so insignificant it's not worth worrying about ever. If you're doing a 100,000 floors it's probably time to switch that logic out of the client.
You may want to have a nose around the v8 source there's some interesting comments there about shaving nanoseconds off functions such as this int.Parse() one.
// Some people use parseInt instead of Math.floor. This
// optimization makes parseInt on a Smi 12 times faster (60ns
// vs 800ns). The following optimization makes parseInt on a
// non-Smi number 9 times faster (230ns vs 2070ns). Together
// they make parseInt on a string 1.4% slower (274ns vs 270ns).
As far as I understand JavaScript logic, everything you refer to as something is searched in the global variable scope. In browser implementations, the window object is the global object. Hence, when you are asking for window.Math you actually have to de-reference what window means, then get its properties and find Math there. If you simply ask for Math, the first place where it is sought, is the global object.
So, yes- calling Math.something will be faster than window.Math.something.
D. Crockeford talks about it in his lecture http://video.yahoo.com/watch/111593/1710507, as far as I recall, it's in the 3rd part of the video.
If Math.round() is being called in a local/function scope the interpreter is going to have to check first for a local var then in the global/window space. So in local scope my guess would be that window.Math.round() would be very slightly faster. This isn't assembly, or C or C++, so I wouldn't worry about which is faster for performance reasons, but if out of curiosity, sure, benchmark it.
While I was investigating functions, I realised that I can create embedded functions. Firstly, I thought it may be useful for structuring code. But now I suppose it isn't good style of coding. Am I right? Here is an example.
function show () {
return function a() {
alert('a');
return function b() {
alert('b');
}
}
}
And I can call alert('b') using this string: show()();
In what situations is better to use this method and in what not?
Yes, this has many uses.
Currying
Firstly, you may want to use currying, where you encapsulate a function with a single argument with a function with many arguments. For example,
function getHandler(num){
return function(){
alert(num);
}
}
myElement.onclick=getHandler(1)
myOtherElement.onclick=getHandler(25)
anotherElement.onclick=getHandler(42)
onclick() cannot be given arbitrary arguments as it is called by the system. Instead of writing 3 different handlers that alert different numbers, this reduces the bloat by creating a function that can generate arbitrary handlers of the "alert a number" type. Of course, this is a rather simplistic example, but if one had to do something considerably more complicated than alert(), the benefits of currying are evident.
Efficiency
Another situation is when you have a complicated function that has one computationally-heavy portion, which is followed by a computationally-light portion. The two portions take different parameters, and usually the parameters for the first portion will be the same. Some variation of memoization can be used to solve this, but function-as-return value works too.
For example, let's say you have a function of the following form:
function doSomething(a,b,c,x,y){
//Do some complicated calculations using a,b,c, the results go to variables e,f,g
//Do some simple calculations using e,f,g,x,y, return result
}
If I want to run doSomething(1,2,3,18,34)+doSomething(1,2,3,55,35)+doSomething(1,2,3,19,12), it would take 3 times the execution time as the long part is execute every time.
However, we can write it as:
function doSomethingCreator(a,b,c){
//Do some complicated calculations using a,b,c, the results go to variables e,f,g
return function(x,y){
//Do some simple calculations using e,f,g,x,y, return result
}
}
Now, all I need to do is call doSomethingCreator() for my set of parameters, and use the created function (which is fast) to get the final results. The code becomes:
var doSomething123=doSomethingCreator(1,2,3);
console.log(doSomething123(18,34)+doSomething123(55,35)+doSomething123(19,12))
One example of this is solving differential equations. Differential equations do not have a single solution if some "boundary conditions" are given. However, (especially for homogenous equations), after one point it is easy to vary the boundary conditions and get solutions. And usually one needs to solve the same equation for different boundary conditions multiple times. So, if you want to write a library method, you would have it take the homogenous equation as the input, and it would return a function, which in turn can be given the boundary conditions as an input to get the final solution.
"Static" variables via closures
Sometimes, you want to be able to easily create a set of variables and carry them around.
For example, if you want to create a counter function:
function generateCounter(){
var c=0;
return function(){
c++;
return c;
}
}
We can use this to make many independent counters, for example:
myCtr1=generateCounter();
myCtr2=generateCounter();
myCtr1(); //Returns 1
myCtr1(); //Returns 2
myCtr2(); //Returns 1
myCtr1(); //Returns 3
myCtr2(); //Returns 2
Each counter is independent. Of course, in this case, it would be easier to jut use myCtr1=0;myCtr2=0 and then the ++ operator, but what if you want to record the times when they were incremented? Extending the ++ case would involve a lot of code duplication, however, here we can tweak it pretty easily:
function generateCounter(){
var c=[]; // The length of c is the value of the counter
return function(){
c.push((new Date()).getTime());
return c;
}
}
When you should not use it
Whenever there is no obvious gain in doing so.
Aside from when you want to use it for closure-bound variables, there usually isn't much point in doing it with 0 arguments for the outer function as the inner function becomes the same function. See if it really improves the program, and then use it.
This is one of the most common styles of coding in Javascript and some other languages which treat their functions as first class citizens. One of the most uses of these nested declarations is in creating closures and currying.
I see this used a lot and I was told putting the function reference between quotes was bad because setTimeout/setInterval evals the reference. What is the actual difference between these two such that one is used over the other and why do I see this used so frequently even though it should be common knowledge that this one way is bad?
People may not realize they can use the unquoted form.
The name referenced in the string may not yet be defined.
The quoted form gives you delayed execution:
setTimeout("myFunction(1, 'hello')", 100)
is easier to understand than:
setTimeout(function () { myFunction(1, 'hello') }, 100)
and this doesn't do what the author wants:
setTimeout(myFunction(1, 'hello'), 100)
There are two main differences between these two forms:
setTimeout("myFunc()", 100);
and
setTimeout(myFunc, 100);
The first is less efficient and it evaluates the function in the global scope so you can't pass it a local function or any function that isn't global.
In a look at the efficiency argument, if you wanted to call a function you had in your code would you write:
x = myFunc();
or would you write:
x = eval("myFunc()");
Of course, you'd write the first one because:
That's how you normally write javascript
The function reference can be resolved once in the first pass of the interpreter rather than each time it executes
Minifiers/optimizers can rename your symbol with the first, but not the second.
You can call local functions with the first one, but the second requires a global function
eval() is a fairly heavyweight thing that should be used only when there is no other better way to do it.
FYI, this jsPerf comparison indicates that the eval() version is 96% slower. The performance might not matter in some circumstances, but you can get the idea how much less efficient it is.
I bet it also prevents memory leaks.
Doesn't leak X:
var x = $("loading");
setTimeout("createTree(1);", 0);
Leak's X:
var x = $("loading");
setTimeout(function(){createTree(1);}, 0);
var recurse = function(steps, data, delay) {
if(steps == 0) {
console.log(data.length)
} else {
setTimeout(function(){
recurse(steps - 1, data, delay);
}, delay);
}
};
var myData = "abc";
recurse(8000, myData, 1);
What troubles me with this code is that I'm passing a string on 8000 times. Does this result in any kind of memory problem?
Also, If I run this code with node.js, it prints immediately, which is not what I would expect.
If you're worried about the string being copied 8,000 times, don't be, there's only one copy of the string; what gets passed around is a reference.
The bigger question is whether the object created when you call a function (called the "variable binding object" of the "execution context") is retained, because you're creating a closure, and which has a reference to the variable object for the context and thus keeps it in memory as long as the closure is still referenced somewhere.
And the answer is: Yes, but only until the timer fires, because once it does nothing is referencing the closure anymore and so the garbage collector can reclaim them both. So you won't have 8,000 of them outstanding, just one or two. Of course, when and how the GC runs is up to the implementation.
Curiously, just earlier today we had another question on a very similar topic; see my answer there as well.
It prints immediately because the program executes "immediately". On my Intel i5 machine, the whole operation takes 0.07s, according to time node test.js.
For the memory problems, and wether this is a "cheap infinite loop", you'll just have to experiment and measure.
If you want to create an asynchronous loop in node, you could use process.nextTick. It will be faster than setTimeout(func, 1).
In general Javascript does not support tail call optimization, so writing recursive code normally runs the risk of causing a stack overflow. If you use setTimeout like this, it effectively resets the call stack, so stack overflow is no longer a problem.
Performance will be the problem though, as each call to setTimeout generally takes a fair bit of time (around 10 ms), even if you set delay to 0.
The '1' is 1 millisecond. It might as well be a for loop. 1 second is 1000. I recently wrote something similar checking on the progress of a batch of processes on the back end and set a delay of 500. Older browsers wouldn't see any real difference between 1 and about 15ms if I remember correctly. I think V8 might actually process faster than that.
I don't think garbage collection will be happening to any of the functions until the last iteration is complete but these newer generations of JS JIT compilers are a lot smarter than the ones I know more about so it's possible they'll see that nothing is really going on after the timeout and pull those params from memory.
Regardless, even if memory is reserved for every instance of those parameters, it would take a lot more than 8000 iterations to cause a problem.
One way to safeguard against potential problems with more memory intensive parameters is if you pass in an object with the params you want. Then I believe the params will just be a reference to a set place in memory.
So something like:
var recurseParams ={ steps:8000, data:"abc", delay:100 } //outside of the function
//define the function
recurse(recurseParams);
//Then inside the function reference like this:
recurseParams.steps--
I'm kind of curious about what the best practice is when referencing the 'global' namespace in javascript, which is merely a shortcut to the window object (or vice versia depending on how you look at it).
I want to know if:
var answer = Math.floor(value);
is better or worse than:
var answer = window.Math.floor(value);
Is one better or worse, even slightly, for performance, resource usage, or compatibility?
Does one have a slighter higher cost? (Something like an extra pointer or something)
Edit note: While I am a readability over performance nazi in most situations, in this case I am ignoring the differences in readability to focus solely on performance.
First of all, never compare things like these for performance reasons. Math.round is obviously easier on the eyes than window.Math.round, and you wouldn't see a noticeable performance increase by using one or the other. So don't obfuscate your code for very slight performance increases.
However, if you're just curious about which one is faster... I'm not sure how the global scope is looked up "under the hood", but I would guess that accessing window is just the same as accessing Math (window and Math live on the same level, as evidenced by window.window.window.Math.round working). Thus, accessing window.Math would be slower.
Also, the way variables are looked up, you would see a performance increase by doing var round = Math.round; and calling round(1.23), since all names are first looked up in the current local scope, then the scope above the current one, and so on, all the way up to the global scope. Every scope level adds a very slight overhead.
But again, don't do these optimizations unless you're sure they will make a noticeable difference. Readable, understandable code is important for it to work the way it should, now and in the future.
Here's a full profiling using Firebug:
<!DOCTYPE html>
<html>
<head>
<title>Benchmark scope lookup</title>
</head>
<body>
<script>
function bench_window_Math_round() {
for (var i = 0; i < 100000; i++) {
window.Math.round(1.23);
}
}
function bench_Math_round() {
for (var i = 0; i < 100000; i++) {
Math.round(1.23);
}
}
function bench_round() {
for (var i = 0, round = Math.round; i < 100000; i++) {
round(1.23);
}
}
console.log('Profiling will begin in 3 seconds...');
setTimeout(function () {
console.profile();
for (var i = 0; i < 10; i++) {
bench_window_Math_round();
bench_Math_round();
bench_round();
}
console.profileEnd();
}, 3000);
</script>
</body>
</html>
My results:
Time shows total for 100,000 * 10 calls, Avg/Min/Max show time for 100,000 calls.
Calls Percent Own Time Time Avg Min Max
bench_window_Math_round
10 86.36% 1114.73ms 1114.73ms 111.473ms 110.827ms 114.018ms
bench_Math_round
10 8.21% 106.04ms 106.04ms 10.604ms 10.252ms 13.446ms
bench_round
10 5.43% 70.08ms 70.08ms 7.008ms 6.884ms 7.092ms
As you can see, window.Math is a really bad idea. I guess accessing the global window object adds additional overhead. However, the difference between accessing the Math object from the global scope, and just accessing a local variable with a reference to the Math.round function isn't very great... Keep in mind that this is 100,000 calls, and the difference is only 3.6ms. Even with one million calls you'd only see a 36ms difference.
Things to think about with the above profiling code:
The functions are actually looked up from another scope, which adds overhead (barely noticable though, I tried importing the functions into the anonymous function).
The actual Math.round function adds overhead (I'm guessing about 6ms in 100,000 calls).
This can be an interest question if you want to know how the Scope Chain and the Identifier Resolution process works.
The scope chain is a list of objects that are searched when evaluating an identifier, those objects are not accessible by code, only its properties (identifiers) can be accessed.
At first, in global code, the scope chain is created and initialised to contain only the global object.
The subsequent objects in the chain are created when you enter in function execution context and by the with statement and catch clause, both also introduce objects into the chain.
For example:
// global code
var var1 = 1, var2 = 2;
(function () { // one
var var3 = 3;
(function () { // two
var var4 = 4;
with ({var5: 5}) { // three
alert(var1);
}
})();
})();
In the above code, the scope chain will contain different objects in different levels, for example, at the lowest level, within the with statement, if you use the var1 or var2 variables, the scope chain will contain 4 objects that will be needed to inspect in order to get that identifier: the one introduced by the with statement, the two functions, and finally the global object.
You also need to know that window is just a property that exists in the global object and it points to the global object itself. window is introduced by browsers, and in other environments often it isn't available.
In conclusion, when you use window, since it is just an identifier (is not a reserved word or anything like that) and it needs to pass all the resolution process in order to get the global object, window.Math needs an additional step that is made by the dot (.) property accessor.
JS performance differs widely from browser to browser.
My advice: benchmark it. Just put it in a for loop, let it run a few million times, and time it.... see what you get. Be sure to share your results!
(As you've said) Math.floor will probably just be a shortcut for window.Math (as window is a Javascript global object) in most Javascript implementations such as V8.
Spidermonkey and V8 will be so heavily optimised for common usage that it shouldn't be a concern.
For readability my preference would be to use Math.floor, the difference in speed will be so insignificant it's not worth worrying about ever. If you're doing a 100,000 floors it's probably time to switch that logic out of the client.
You may want to have a nose around the v8 source there's some interesting comments there about shaving nanoseconds off functions such as this int.Parse() one.
// Some people use parseInt instead of Math.floor. This
// optimization makes parseInt on a Smi 12 times faster (60ns
// vs 800ns). The following optimization makes parseInt on a
// non-Smi number 9 times faster (230ns vs 2070ns). Together
// they make parseInt on a string 1.4% slower (274ns vs 270ns).
As far as I understand JavaScript logic, everything you refer to as something is searched in the global variable scope. In browser implementations, the window object is the global object. Hence, when you are asking for window.Math you actually have to de-reference what window means, then get its properties and find Math there. If you simply ask for Math, the first place where it is sought, is the global object.
So, yes- calling Math.something will be faster than window.Math.something.
D. Crockeford talks about it in his lecture http://video.yahoo.com/watch/111593/1710507, as far as I recall, it's in the 3rd part of the video.
If Math.round() is being called in a local/function scope the interpreter is going to have to check first for a local var then in the global/window space. So in local scope my guess would be that window.Math.round() would be very slightly faster. This isn't assembly, or C or C++, so I wouldn't worry about which is faster for performance reasons, but if out of curiosity, sure, benchmark it.