mobxjs / mobx

Simple, scalable state management.
http://mobx.js.org
MIT License
27.47k stars 1.77k forks source link

Will mobservable perform if used at scale? #39

Closed rymohr closed 8 years ago

rymohr commented 8 years ago

Just came across this library and I'm intrigued. Most of the work I'm doing at this point is graph related with a potentially large number of nodes, edges, and properties for each. Any idea how well performance holds up when your state is composed of hundreds of thousands of objects?

mweststrate commented 8 years ago

Could you elaborate on your question a bit more? Are you interested in the overhead on the structures themselves / derived computations or in the context with DOM updates using for example React?

Anyway, some old benchmarks can be found in this blogpost (Performance has even improved since then). During the today's talk at Reactive2015 I explained why it is faster in combination with React then most other approaches (saddly, first part of the talk is still missing but the first 15 minutes of the video are the second half of the presentation).

But feel free to ask more details ;-)

rymohr commented 8 years ago

Mostly in the overhead of the structures themselves.

At my work we originally used the update-everything-automatically approach and ran into major performance issues with larger graphs (5k nodes, 15k edges, with node positions updating each tick). There was no easy way around the performance issues when you had no control over when the derived computations were updated. We ended up switching to an explicit update model with mutable state and, although there's more code to maintain, performance is much better.

As the author of this library I was just curious if you had any insights on where this approach starts to fall apart.

BTW please let me know if you find a full copy of the presentation. I'd love to watch the whole thing.

mweststrate commented 8 years ago

Hi Ryan,

Thanks to the explanation. It's hard to say something specific about it, but so far we have been able to work with ten thousands of observable values with significant overhead. Of course it depends on how expensive your derived calculations are, but so far the bottleneck usually seems to be the DOM, even when we generate bezier curves on the fly during drag and drop. Anyway, the overhead of being observable in itself is neglectable; overhead comes primarily from performing computations on the observable data which might be expensive. Here are some details about how mobservable tries to minimize the amount of computations:

Mobservable will always recompute affected views synchronously when related data changes.

rymohr commented 8 years ago

Thanks for the detailed breakdown Michel. I was looking for something like transaction but didn't see anything mentioned in the readme. This may actually work if we're able to batch mutations like that.

Our use case is definitely an edge case. Node positions are updating constantly and the calculations derived from the new positions aren't exactly light weight. The arc for each edge needs to be recalculated, color gradients need to be updated, and the position and orientation of edge arrows need to be recalculated too. And that process is happening roughly 60x per second.

The huge potential benefit I see though is that none of those calculations would run if the node positions haven't changed. And we wouldn't have to do any of our own dirty tracking.

mattruby commented 8 years ago

We've played with transaction a bit, it's pretty straight forward. Here's one of Michel's examples that uses is: https://github.com/mweststrate/mobservable-reactive2015-demo/blob/96916cac44ff080b037b085f29d13ef3de346a2e/src/stores/domain-state.js

On Thu, Nov 5, 2015 at 1:09 PM, Ryan Mohr notifications@github.com wrote:

Thanks for the detailed breakdown Michel. I was looking for something like transaction but didn't see anything mentioned in the readme. This may actually work if we're able to batch mutations like that.

Our use case is definitely an edge case. Node positions are updating constantly and the calculations derived from the new positions aren't exactly light weight. The arc for each edge needs to be recalculated, color gradients need to be updated, and the position and orientation of edge arrows need to be recalculated too. And that process is happening roughly 60x per second.

The huge potential benefit I see though is that none of those calculations would run if the node positions haven't changed. And we wouldn't have to do any of our own dirty tracking.

— Reply to this email directly or view it on GitHub https://github.com/mweststrate/mobservable/issues/39#issuecomment-154156166 .

-Matt Ruby- mattruby@gmail.com

mweststrate commented 8 years ago

And this is probably also good to know: If you have reactive computations that always return a quite simple but new object or array with for example coordinates, you can make sure that mobservable does structural equality checks instead of reference equality checks before something is detected as being changed by wrapping the function in asReference as described in the docs

mweststrate commented 8 years ago

Please feel free to write any tests in babel! Some of the unit tests are in babel as well (code transpiled with babel is quite different from typescript compiled code, so babel is already included in the dev dependencies).

On Mon, Nov 9, 2015 at 12:06 PM, Jiri Spac notifications@github.com wrote:

would be certainly interesting to see some benchmarks in the repo. I would even offer to write some myself, but I would write that in babel, not typescript and you wouldn't like that, since this is typescript.

— Reply to this email directly or view it on GitHub https://github.com/mweststrate/mobservable/issues/39#issuecomment-155029819 .

capaj commented 8 years ago

sorry, I was judging before I even looked at it.That's why I deleted my comment. Will try to find the time to write some more benchmarks if I can find spare time.

On Mon, Nov 9, 2015 at 11:14 AM, Michel Weststrate <notifications@github.com

wrote:

Please feel free to write any tests in babel! Some of the unit tests are in babel as well (code transpiled with babel is quite different from typescript compiled code, so babel is already included in the dev dependencies).

On Mon, Nov 9, 2015 at 12:06 PM, Jiri Spac notifications@github.com wrote:

would be certainly interesting to see some benchmarks in the repo. I would even offer to write some myself, but I would write that in babel, not typescript and you wouldn't like that, since this is typescript.

— Reply to this email directly or view it on GitHub < https://github.com/mweststrate/mobservable/issues/39#issuecomment-155029819

.

— Reply to this email directly or view it on GitHub https://github.com/mweststrate/mobservable/issues/39#issuecomment-155031030 .