NEW 143239
No way to quickly make non-enumerable instance properties
https://bugs.webkit.org/show_bug.cgi?id=143239
Summary No way to quickly make non-enumerable instance properties
Ryosuke Niwa
Reported 2015-03-30 16:07:45 PDT
I was talking with https://twitter.com/stefanpenner (Ember.js core member) and he told me that they currently work around the fact we can't create a non-enumrerable property fast. SpiderMonkey bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1088453 V8 bug: https://code.google.com/p/v8/issues/detail?id=3649
Attachments
Ryosuke Niwa
Comment 1 2015-03-30 16:10:16 PDT
I've manually enabled symbols in JSC and got results on https://jsperf.com/symbol-vs-prop-vs-def-prop: property 68,907,822 ±0.30% fastest non-enumerable 4,093,475 ±0.58% 94% slower symbol 11,586,795 ±0.36% 83% slower weakmap 5,361,775 ±2.15% 92% slower
Filip Pizlo
Comment 2 2015-03-30 16:12:43 PDT
That's super interesting. I think that the main problem is that making a property non-enumerable doesn't involve a cached transition. This means that if you make something non-enumerable, all accesses to the object go slow after that. Once we fix that, then the next problem is that the call to make it non-enumerable is not intrinsic. We should make that call be intrinsic.
Ryosuke Niwa
Comment 3 2015-03-30 16:15:08 PDT
Accessing a property using symbol seems pretty fast (http://jsperf.com/symbol-vs-property/13): symbol 18,871,149 ±0.94% 28% slower property 18,106,575 ±0.42% 31% slower .foo 26,093,814 ±0.53% fastest (Chrome results are somewhat misleading because it ran on a much faster results; what's important is the relative perf. of different cases).
Filip Pizlo
Comment 4 2015-03-30 16:15:52 PDT
(In reply to comment #1) > I've manually enabled symbols in JSC and got results on > https://jsperf.com/symbol-vs-prop-vs-def-prop: > > property 68,907,822 ±0.30% fastest > non-enumerable 4,093,475 ±0.58% 94% slower > symbol 11,586,795 ±0.36% 83% slower > weakmap 5,361,775 ±2.15% 92% slower The best way to benchmark this is to take a medium-sized test that is known to create a lot of objects and access a lot of properties, and modify it to make all of the properties non-enumerable. Then also make a version that uses symbols. Then also make a version that uses WeakMap. That is, uses those things for all of the properties. I recommend either V8/deltablue or V8/raytrace. V8/raytrace could be hilarious since in that one we do very aggressive object allocation sinking but we can't do it if you do things we don't optimize (like all of the things you list above). So, just make three new versions of raytrace: raytrace-non-enum raytrace-symbol raytrace-weakmap I know it's tedious, but this is what I do when I want to come up with a good story for optimizing a feature. Like, we have getter-richards for when I was optimizing getters/setters, and now we have deltablue-varargs to help me with my varargs optimization work.
Ryosuke Niwa
Comment 5 2015-03-30 16:16:57 PDT
(In reply to comment #2) > Once we fix that, then the next problem is that the call to make it > non-enumerable is not intrinsic. We should make that call be intrinsic. Since class methods are non-enumerable (bugs 143181), we should add the intrinsic for defineProperty anyway.
Ryosuke Niwa
Comment 6 2015-03-30 16:18:02 PDT
Oh these are tests made by Ember.js folks. Also see the original bug report by https://twitter.com/stefanpenner at https://code.google.com/p/v8/issues/detail?id=3649 and https://bugzilla.mozilla.org/show_bug.cgi?id=1088453. I've asked him to file a bug but he's really busy right now so I'm doing it on his behalf.
Filip Pizlo
Comment 7 2015-03-30 16:21:07 PDT
(In reply to comment #3) > Accessing a property using symbol seems pretty fast > (http://jsperf.com/symbol-vs-property/13): > > symbol 18,871,149 ±0.94% 28% slower > property 18,106,575 ±0.42% 31% slower > .foo 26,093,814 ±0.53% fastest > > (Chrome results are somewhat misleading because it ran on a much faster > results; what's important is the relative perf. of different cases). No. Relative perf doesn't matter. It's possible that just adding a symbol-keyed property puts the prototype into a slower mode, in which case this test is bogus. If Chrome is much faster on basic property accesses in your test then one of the following is happening: - Our property accesses are completely busted and we should go back to the drawing board. Unlikely, since we are very competitive on property access tests. - Putting symbols into an object makes accesses to even normal properties slower, in which case "accessing a property using a symbol seems pretty fast" is an incorrect conclusion. - jsperf puts each microbenchmark snippet into some kind of bizarro loop, and we're running that loop slowly. I.e. you're not even testing property access performance but you're just testing the performance of the jsperf harness. Anyway, it's completely wrong to conclude that something is fast the baseline (accessing .foo) is an order of magnitude slower than Chrome.
Ryosuke Niwa
Comment 8 2015-03-30 18:23:02 PDT
Alright, I've made a slightly better micro benchmark at https://gist.github.com/rniwa/572ed56668366e6542d3 It doesn't seem like defining or accessing symbol properties isn't significantly slower: Defining string properties: 242 ms Accessing string properties: 95 ms Defining symbol properties: 271 ms Accessing string properties: 143 ms
Ryosuke Niwa
Comment 9 2015-03-30 18:28:33 PDT
(In reply to comment #7) > > Anyway, it's completely wrong to conclude that something is fast the > baseline (accessing .foo) is an order of magnitude slower than Chrome. I don't think anyone is claiming that here. This bug is about Ember.js wanting to define and access non-enumerable property without runtime penalty. Either making defineProperty fast or symbols perform as fast as strings would work (although we should really do both!)
Note You need to log in before you can comment on or make changes to this bug.