New issue
Advanced search Search tips
Starred by 42 users

Issue metadata

Status: Fixed
Owner:
Closed: Jan 2014
Cc:
HW: ----
NextAction: ----
OS: ----
Priority: ----
Type: ----



Sign in to add a comment

Iteration over frozen object is slow

Reported by kan...@gmail.com, Dec 9 2011

Issue description

See http://jsperf.com/performance-frozen-object

It looks like there's a a significant performance hit when iterating over frozen object (`Object.freeze(...)`) in V8. Notice that nightly Firefox, WebKit, and Opera don't exhibit such behavior.
 
I'm seeing this too.  If it was a minor performance hit, I wouldn't care too much, but it's severe.  In when.js (https://github.com/cujojs/when), I see a 10x performance increase when I use a noop function instead Object.freeze() in v8.

I also believe that this happens when Object.defineProperty and Object.defineProperties are used to create properties that are effectively frozen, i.e. writable: false, configurable: false.  I don't have a test case for that yet, but based on quick tests using when.js, I'm fairly sure it's the case.
I hear about our frozen object performance quite often from developers. Is there anything we can do here to help?
Various promise libraries (Q and when for instance) use Object.freeze extensively. With the increasing popularity of promises, it makes sense to me that V8 increase its performance where necessary.

Comment 4 by mac...@gmail.com, Mar 7 2013

What else is required to duplicate this issue? Accessing all the fields on a simple (but big) object does not repro the results for me. 

See: http://jsperf.com/issue-1858
Running: Chrome 26.0.1410.19 32-bit on Windows 8 64-bit
I found your test very interesting so I decided to run my own. There are a few ways your test differs from the original one posted: use of literals, cloning, and size of data. I created this test (http://jsperf.com/issue-1858/2) to hopefully gain more insight. It seems that there is no difference when using literals or cloning an object. There is, however, an interesting thing that happens when the number of keys increases. When using small objects - 10 keys in my test - there is a huge difference in performance. As the number of keys is increased to 100, there appears to be no distinguishable difference in performance.
The performance difference is due to the backing store data structure. For few properties, the object descriptor describes where the properties are stored, in a property array. If the number of properties grow, we eventually switch to a dictionary for backing store, which is less performant, but more flexible.
When we freeze an object, what is being done is that all properties are set to unconfigurable and unwritable. Storing those attributes is only possible in a dictionary backing store, so we switch to that.

Comment 7 by mac...@gmail.com, Mar 9 2013

Looks like it's not the shallow number of properties, but the deep (total) number of properties? e.g. this test with deep hierarchy of 10 properties -> 10 properties -> 10 properties shows no significant performance difference either.

See: http://jsperf.com/issue-1858/3
Running: Chrome 26.0.1410.19 32-bit on Windows 8 64-bit

Comment 8 by edy.b...@gmail.com, Apr 14 2013

Is it not possible to freeze the object in a way that doesn't change the backing store to something that visibly affects performance?
#8: not without big changes to the way we store object properties. Fast properties simply don't contain property attributes, which are necessary to indicate freeze of the object.

Comment 10 by cgw...@gmail.com, Apr 15 2013

#9: Could the needed properties on the containing object, rather than the individual properties?

Comment 11 by edy.b...@gmail.com, Apr 15 2013

#9 I should've phrased my question better: can the object be marked as frozen without touching the properties and the backing store *at all*? (though #10 just asked the same thing anyway)
I guess that would be possible by changing the map. But then we would have to add an additional check everywhere we write to any property.
Cc: verwa...@chromium.org
Owner: adamk@chromium.org
Status: Accepted
What's mentioned in #9 isn't exactly true. Fast properties are described in the descriptor array with attributes. We can clone the map, copy the descriptor array and change the properties. If we also keep a transition to that map, things will be pretty damn fast.

This exactly what adamk is working on in https://codereview.chromium.org/14888005/.

The caveat: for now elements / JSArrays are not supported at all.

Comment 14 by agoode@google.com, Dec 21 2013

Is this issue resolved with the closing of https://codereview.chromium.org/14888005/?

Comment 15 by mac...@gmail.com, Dec 21 2013

Appears not. Results of OP's test still seem consistent with original report. Chrome Version 32.0.1700.68 beta-m  http://jsperf.com/performance-frozen-object
This certainly appears to continue to be an issue:

Browser: Chrome 34.0.1796.0 canary

Test Case: http://jsperf.com/performance-frozen-object

Result: 115,802,994±0.83% Ops/sec vs. 8,500,655±0.44% Ops/sec
Status: Fixed
Thanks for pinging this issue, it fell off my radar. This will be fixed by https://codereview.chromium.org/135903014/.
Performance of frozen object was increased from v3.24.21.
Can we also do about sealed object?

http://jsperf.com/performance-frozen-object/20
I'd like to +1 #18 on that, but a separate bug should be filed for that.

Sign in to add a comment