gadget-inc / mobx-quick-tree

A mirror of the mobx-state-tree API that supports creating a fast, non-reactive, read-only tree
MIT License
15 stars 2 forks source link

Generate a monomorphic version of `.createReadOnly` and `.instantiate` for each class model #74

Closed airhorns closed 10 months ago

airhorns commented 10 months ago

The VScode Deopt explorer showed that .createReadOnly inside the class model register function was getting deoptimized because it closes over too-wide a variety of klass variable references. We're closing over it so it is correct, but to v8, the callsite is still the same I guess, so it has to deoptimize to pull the right value for the closure! Same for .is and .instantiate -- these dynamically produced functions make a huge difference if they are re-eval'd for each class instead of defined dynamically.

CleanShot 2023-11-12 at 22 57 15

Removing this deoptimization recovered a lot of the node 18 => node 21 performance gap for me! Not all of it. It also makes node 18 faster, but not by nearly as much.

On main on node 18

instantiating a small root x 3,105,456 ops/sec ±0.15% (100 runs sampled)
instantiating a large root x 6,289 ops/sec ±0.68% (99 runs sampled)
instantiating a large union x 803,839 ops/sec ±1.33% (98 runs sampled)
instantiating a diverse root x 881,149 ops/sec ±1.35% (99 runs sampled)

On main on node 21

instantiating a small root x 1,942,360 ops/sec ±0.75% (94 runs sampled)
instantiating a large root x 3,725 ops/sec ±1.61% (93 runs sampled)
instantiating a large union x 468,432 ops/sec ±1.57% (95 runs sampled)
instantiating a diverse root x 604,151 ops/sec ±0.19% (96 runs sampled)

On branch on node 18

instantiating a small root x 3,047,781 ops/sec ±0.30% (95 runs sampled)
instantiating a large root x 6,842 ops/sec ±2.48% (96 runs sampled)
instantiating a large union x 1,085,365 ops/sec ±1.45% (99 runs sampled)
instantiating a diverse root x 983,455 ops/sec ±1.39% (100 runs sampled)

On branch on node 21

instantiating a small root x 1,904,508 ops/sec ±0.52% (99 runs sampled)
instantiating a large root x 5,247 ops/sec ±0.29% (98 runs sampled)
instantiating a large union x 523,979 ops/sec ±1.31% (95 runs sampled)
instantiating a diverse root x 1,040,574 ops/sec ±1.07% (101 runs sampled)