Object property lookups aren't free. The 'global namespace chain' code has to lookup the util property in the Library object, then the add function in the util object.
It's not particularly expensive, but if you do it in a tight loop 100k times it'll look slow compared to something that doesn't need to do that work.
As others have said, the trick is simply to perform those lookups earlier and assign the resulting function/data to a variable.
I'm not sure it would be legal to fix up automatically. What is expected if you have a background timer which could change "window.Library.util" at some point? If you resolve every time, you'll get a new "add()", if you cache, you'll get the same.
Are you saying that the V8 JIT won't catch this? What if it optimizes _any_ function/module/etc. that is later changed? The optimization should be discarded when the reference is reassigned. If it's not, then V8 has a bug that should be manifesting everywhere.
The problem is that the code is not semantically identical, there is no way for the compiler to know that nothing else has changed while the loop is executing. It's like the frequent optimization case of
int len = array.length
for(i = 0; i < len; i++){
}
vs.
for(i = 0; i < array.length; i++){
}
The code is semantically different and therefore has a different performance profile.
Depends what you mean by "changed". The function body itself cannot change in javascript afaik. The function bound to some name can change, but that's equivalent to the name pointing at another structure. The new structure will have its own compiled version of the new function. It doesn't mean though that it can just fold multiple resolutions of the same name into a local variable and cache it. This kind of behaviour would be similar to optimising random() to return 4.
I'm not sure if v8 does any whole-module optimisations... if it does, then there's got to be loads of "invalidate me" hooks everywhere. I doubt it would be worth doing, but if anyone has more precise info - please correct me :)
This appears to be micro-benchmarking the result of incrementing an integer by calling a function that calls a function nested in a bunch of object properties, vs. the same, but the called function lives in a closure.
Moral of the story? Perhaps, "make local aliases for objects used in performance-critical loops." Nothing new here.
Certainly not a good argument for one style of JavaScript library over the other (which seems to be the aim).
What's really unfortunate is that this appears to be deliberately misleading. The writer of the test is either acting maliciously or doesn't have nearly enough understanding of how Javascript works to be making such an assertion.
Could you be specific about what was deliberately misleading? You've made the assertion but didn't specify what you were referring to. Sad to see that kind of silliness on HN.
It's deliberately misleading to say that jQuery and other libraries use a pattern where (internal to the library) there are constant, deep chain lookups. The entire "problem" can be easily "fixed" with the solution above--cache local references so you're not doing deep-lookups constantly (which, if you look at the source of the referenced libraries, you won't find).
As I said; it's either deliberately misleading--or the author's understanding of javascript is too limited as to be making claims that "jQuery and other libraries could have been 98% faster." A comment, by the way, which was later modified to state "if you are not a JavaScript Ninja your framework code could have been up to 98% faster."
Sorry, I don't file that knowledge under "Javascript Ninja" knowledge--and moreover, the original comment was designed to say, "My library is faster / better than all of these popular libraries."
[Edit] To my (admittedly cynical at times) that adds up to deliberately misleading.
If you read the comments, it turns out that he's not really aiming to show anything, just experimenting. It's just interesting to know quite how severe the costs of global namespace lookups can be, for me.
In your tests the method "add" is pretty far away from it's original variable, and MUCH further away than any jQuery method is, so you're also testing the time it takes to lookup that method. In jQuery, methods are either attached to "jQuery" directly or on the prototype.
That's (part of) the premise of the "myjs" library demoed at PariJS last month too - http://myjs.fr/ - get rid of scope chain access and speed things up.
What's the difference between writing myLibrary.foobar and myLibrary_foobar? Everyone got too caught up with Java-style module naming convention to bother to figure out how JavaScript actually worked (or to notice that the Java compiler flattens the package hierarchy).
24 comments
[ 5.0 ms ] story [ 49.9 ms ] threadIt's not particularly expensive, but if you do it in a tight loop 100k times it'll look slow compared to something that doesn't need to do that work.
As others have said, the trick is simply to perform those lookups earlier and assign the resulting function/data to a variable.
I have no idea how boring and where dynamic web-paging would be today without JS!
I'm not sure if v8 does any whole-module optimisations... if it does, then there's got to be loads of "invalidate me" hooks everywhere. I doubt it would be worth doing, but if anyone has more precise info - please correct me :)
Moral of the story? Perhaps, "make local aliases for objects used in performance-critical loops." Nothing new here.
Certainly not a good argument for one style of JavaScript library over the other (which seems to be the aim).
Sad to see this kind of silliness on HN.
As I said; it's either deliberately misleading--or the author's understanding of javascript is too limited as to be making claims that "jQuery and other libraries could have been 98% faster." A comment, by the way, which was later modified to state "if you are not a JavaScript Ninja your framework code could have been up to 98% faster."
Sorry, I don't file that knowledge under "Javascript Ninja" knowledge--and moreover, the original comment was designed to say, "My library is faster / better than all of these popular libraries."
[Edit] To my (admittedly cynical at times) that adds up to deliberately misleading.
nevertheless it shows that if you don't keep those rules in mind all the time you might end up with very slow code.
Thanks for your comment though!
http://jsperf.com/global-namespace-chain-vs-string-based-loc...
In your tests the method "add" is pretty far away from it's original variable, and MUCH further away than any jQuery method is, so you're also testing the time it takes to lookup that method. In jQuery, methods are either attached to "jQuery" directly or on the prototype.
As other people have mentioned, here we see identical perf when moving the add function lookup out of the inner loop.