tc39 / proposal-class-fields

Orthogonally-informed combination of public and private fields proposals
https://arai-a.github.io/ecma262-compare/?pr=1668
1.72k stars 113 forks source link

class fields with [[Define]] semantics are much slower than with [[Set]] semantics. #321

Closed trusktr closed 4 years ago

trusktr commented 4 years ago

perf.link benchmark

The difference is huge. 1,564,910 ops/s for "instance props" ( [[Set]] ) vs 265,260 ops/s for "class fields" ( [[Define]] ) on my machine, in Chrome.

robpalme commented 4 years ago

Thanks for the performance report @trusktr. Here's what I see on my Windows 10 X1 laptop.

Browser Public Fields (op/s) Constructor Assignment (op/s) Relative Diff
Chome 87 166,340 963,506 5.8x
Firefox 81 119,780 318,450 2.7x

It's common for there to be a bit of chicken-and-egg between feature adoption and the point at which browsers optimize features. ES2015 features were far from fast in 2015 - in fact ES5 equivalent code would often be faster than ES2015 syntax - but on the whole it has now been rectified.

It looks like V8 may already know about public field performance. There's V8 issue 9888 for a potential optimization:

public field initializers were changed to use CreateDataProperty. We should add IC support back for this, especially for instance field initializers

trusktr commented 4 years ago

I was thinking about it, and if this.foo = 0 creates a new descriptor on this (when there isn't a base class accessor to call instead), then I would think that class fields with [[Define]] semantics should be the same speed because they also just create a descriptor (except they will avoid prototype lookup for an accessor, so maybe they should even be faster than [[Set]] in all cases).

trusktr commented 4 years ago

I'm going to close this, because logically there's doesn't seem to be any reason why [[Define]] semantics would be any slower than [[Set]] without the presence of accessors (getters/setters).

In my mind (now that @robpalme mentioned engine optimization), there can't possibly be any explanation for the [[Define]] semantic slowness other than that engine developers haven't copied over the optimization from the [[Set]] implementation.