sylvainpolletvillard / ObjectModel

Strong Dynamically Typed Object Modeling for JavaScript
http://objectmodel.js.org
MIT License
467 stars 30 forks source link

performance: extended getters getting called 3 times internally #120

Closed gotjoshua closed 4 years ago

gotjoshua commented 4 years ago

So, we used to use ObjectModel for both our data objects (OMs) and ViewModels (VMs) The VM was a very simple ObjectModel that only needed to check that it's _om prop was an instance of the correct OM. Then the VM is extended (as the model is not "sealed") with many getters that do not need to be validated. Today we discovered that the getters are called 3 times internally to ObjectModels get function. We promptly transformed our BaseVM into a normal object and see noticeable differences across all UI interaction.

I made a code pen to illustrate: https://codepen.io/gotjoshua/pen/qBdmJQP

getterCalled3x

I know that using ObjectModel comes at a cost, but 3x on all calls to getters that don't need validation at all seems excessive.

gotjoshua commented 4 years ago

I think simply caching o[key] in a const before this code block at L#278 could at least help a bit:

if (o[key] && has(o, key) && !isPlainObject(defPart) && !isModelInstance(o[key])) {
  o[key] = cast(o[key], defPart) // cast nested models
}

if (isFunction(o[key]) && key !== "constructor" && !privateAccess) {
  return grantPrivateAccess(o[key])
}

if (isPlainObject(defPart) && !o[key]) {
  o[key] = {} // null-safe traversal
}
sylvainpolletvillard commented 4 years ago

That seems totally right. Thanks for the investigation, will try to push a new version today

sylvainpolletvillard commented 4 years ago

Fixed in v4.0.6

gotjoshua commented 4 years ago

Is there a tag for that?

sylvainpolletvillard commented 4 years ago

Added a git tag.

gotjoshua commented 4 years ago

I made another pen that does 1000 instantiations and 1000 calls to a getter that also uses another getter. The difference is noticeable between 4.0.6 and 4.0.5!

However, the performance compared to normal objects is still a bit disturbing:

4.0.5

4 0 5

4.0.6

4 0 6