Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mobx how to cache computed values?

I'am using Mobx to build a webgl game engine. I am not using it with react. I am using it to enhance an entity component system. I have entity classes like

import {observable, observe, computed, autorun} from 'mobx';

class Entity {
  @observable position = [0,0,0]
  @observable rotation = [0,0,0]

  @computed get modelMat(){
    return position * rotation;
  }
}

I use this entity like :

var ent = new Entity();
entity.position = [0,10,0];
if(entity.modelMat == 6){
  // do something
}

My understanding is that reading modelMat directly like that is not a best practice. It causes the computed to be recalculated. It is not cached. This is detrimental in my game engine as I might be accessing these computed values at a high velocity like 60fps.

This seems unintuitive to me because you define the computed using the get helper and then are not supposed to use it as a getter? The debug computedRequiresReaction setting is available to prevent this pattern of direct computed reading.

configure({
  computedRequiresReaction: true
});

My question then is how to cache or memoize these computed values that will be accessed at frequent intervals? To avoid this I have started using a pattern that uses autoruns, to update local variables when the computed changes. It looks like:

class Entity {
  @observable position = [0,0,0]
  @observable rotation = [0,0,0]

  modelMat = []

  constructor(){
    autorun(() => {
      this.modelMat = this.computedModelMat()
    })
  }

  @computed get computedModelMat(){
    return position * rotation;
  }
}

This enables an interface for the class so that ent.modelMat can still be accessed rapidly but its not re-computed each time. Is there a better suggested pattern for this? It seems redundant to have an autorun for each computed. some of my classes end up having many autorun handlers to cache these values.

like image 245
kevzettler Avatar asked Nov 06 '25 18:11

kevzettler


1 Answers

Note that computed supports a keepAlive option, that will force mobx to cache the value, even when there are no observers. And it is actually more efficient than using autorun to observe, as there are some internal optimizations applied to this flag.

There is a little risk of memory leaks though: if anything referred to by the computed is still alive, the computed won't be cleaned up. However, if you are only referring to class local things this should be save.

like image 119
mweststrate Avatar answered Nov 09 '25 08:11

mweststrate



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!