So this is an interesting one... While I was testing the performance of setAttribute vs. normal property set on an element, I found an odd behavior, which I then tested on regular objects and... It's still odd!
So if you have an object A = {}
,
and you set its property like A['abc_def'] = 1
, or A.abc_def = 1
, they are basically the same.
But then if you do A['abc-def']
= 1 or A['123-def']
= 1 then you are in trouble. It goes wayyy slower.
I set up a test here: http://jsfiddle.net/naPYL/1/. They all work the same on all browsers except chrome.
The funny thing is that for "abc_def" property, chrome is actually much faster than Firefox and IE, as I expected. But for "abc-def" it's at least twice as slow.
So what happens here basically (at least from my tests) is that when using "correct" syntax for properties (legal C syntax, which you can use with dot properties) - It's fast, but when you use syntax that requires using brackets (a[...]) then you're in trouble.
I tried to imagine what implementation detail would distinguish in such a way between the two modes, and couldn't. Because as I think of it, if you do support those non-standard names, you are probably translating all names to the same mechanics, and the rest is just syntax which is compiled into that mechanic. So . syntax and [] should be all the same after compilation. But obviously something is going the other way around here...
Without looking at V8's source code, could anyone think of a really satisfying answer? (Think of it as an exercise :-))
Here's also a quick jsperf.com example
Thanks to NDM for the jsperf example!
Edit:
To clarify, of course I want also a concrete answer from the real code (which I already found) or to be more precise - the reason behind that specific implementation. That is one of the reasons I asked you to look at it "as an exercise", to look behind the technical implementation and try to find the reason.
But I also wanted to see how other people's minds work in cases like these. This may sound "vague" to some of you - but it is very useful to try and think like other people from time to time, or take their point of view. It enhances your own ways of thinking.
The process works like this: Chrome Canary is released with the latest features and updates, and updated nightly. After a period, any bugs that were found are fixed, and that version filters downward to the Dev release channel. The same process is completed for Dev, then the release is passed on to the Beta channel.
The new "Partially presented frames" aims to indicate more intuitively that although some content is not presented timely in the frame, but the issue is not so severe as to block visual updates altogether.
So JS objects can be used for two conflicting purposes. They can be used as objects but they can be used as hash tables too. However what is fast and makes sense for objects is not so for hash tables, so V8 tries to guess what a given object is.
Some signs the user can give that he wants a dictionary are deleting a property or giving a property a name that cannot be accessed using dot notation.
Some other heuristics are also used, I have made a gist https://gist.github.com/petkaantonov/6327915.
There is however a really cool hack that redempts an object from hash table hell:
function ensureFastProperties(obj) {
function f() {}
f.prototype = obj;
return obj;
}
See it in action: http://jsperf.com/property-dash-parformance/2.
The redempted object is not as fast as the original because the properties are stored in the external properties array rather than in-object. But that's still far better than hash table. Note that this is still pretty broken benchmark, do not think for a second that hash tables are only 2x slower than inobject properties.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With