Closed trusktr closed 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
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).
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.
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.