Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ideas for optimizing Blaze #111

Closed
mitar opened this issue Sep 24, 2016 · 13 comments
Closed

Ideas for optimizing Blaze #111

mitar opened this issue Sep 24, 2016 · 13 comments

Comments

@mitar
Copy link
Contributor

mitar commented Sep 24, 2016

Let's start collecting ideas how we could optimize Blaze better. (For more great discussion about this you can check discussions in #103 and #45. This issue is trying to distill and organize those discussions.)

  • data context level, equality being what it is, which triggers reruns on any non-primitive value change:
    • possible solutions:
      • get rid of data context
      • allow custom data context with custom equality function
  • tracker level, which is similar to data context level, but means that in general any reactive dependency might rerun more often than necessary (Unnecessary re-rendering in Blaze because with's ReactiveVar uses default equals function #68)
    • possible solutions:
      • using something like computed field to be precise about dependency changes
  • no tracker caching level: if you have autorun with multiple dependencies, when one of those change, also other are recomputed, instead of previously returned value just cached and returned
  • minimongo and array processing level: we want changes to be triggered only when data really changes, and only for those changes
  • blaze data level (what you are talking about here, I think): that propagation of data through blaze might be ineffective and be done when data has not really changed
  • HTMLJS materialization level: when HTMLJS does not really change, but Blaze still builds DOM elements and does diff against DOM
  • interacting with DOM level: querying DOM for state is often expensive
  • optimize _.bind
  • it seems that observe sequence is still called even when non-reactive cursor is returned from a template helper: the reason is probably because template helpers depend on data context so it can potentially return different non-reactive cursors as it reruns, but maybe we could provide some way to return static arrays which we know will never change and then do not observe changes at all
@mitar mitar added this to the Next minor version milestone Sep 24, 2016
@mitar
Copy link
Contributor Author

mitar commented Sep 26, 2016

I made this test case for benchmarking the first rendering of Blaze. Not updates. To have a baseline and see what we can improve.

@mitar
Copy link
Contributor Author

mitar commented Sep 26, 2016

@stubailo: Can you check if I am doing a React rendering in a reasonable way? I want to have it around so that I can compare.

@mitar
Copy link
Contributor Author

mitar commented Sep 26, 2016

It is interesting that React spends the same amount of time switching between two tables which are completely different and between one table and another which is only 50% different. I thought it will a diff and replace only 50% of those DOM elements, so spend around 50% less time.

@nathan-muir
Copy link
Contributor

@mitar I wonder how mobx (previously mobservable) would fare instead of tracker -

> MobX builds a virtual derivation graph to minimize the number of recomputations needed to keep derivations in sync with the state.

I think it might solve issues in Blaze regarding re-rendering inner vs, outer templates; by figuring out which computations the others depend on and re-computing those first.

@mitar
Copy link
Contributor Author

mitar commented Sep 27, 2016

I have no idea about that one. Feel free to investigate. :-) But I think we might have some other low-hanging fruits first.

@mitar mitar removed this from the Next minor version milestone Sep 30, 2016
@mitar
Copy link
Contributor Author

mitar commented Nov 28, 2016

One interesting test case to test against: meteor/meteor#3733

@mitar
Copy link
Contributor Author

mitar commented Jan 2, 2017

Tracker is used a lot in Blaze. I am seeing that every time a computation is rerun, withNoYieldsAllowed is called. This could be probably called only once at the beginning when computation is constructed.

@janat08
Copy link

janat08 commented Aug 23, 2017

You heard my complaints about setter/getter not working with arrays, while blaze only renders array lists, and so perhaps we could consider switching to proxies as you explained was my true solution.

@janat08
Copy link

janat08 commented Jan 15, 2018

hyperhtml, view lib, is pretty fast and weights nothing with basic api such that it supports all the browsers. Uses template literals.

@janat08
Copy link

janat08 commented Jan 16, 2018

Anyway blaze slowness is due to rendering or tracking?

@ghost
Copy link

ghost commented Aug 15, 2019

@mitar Are you still willing to take some PR's on some of these issues? I am currently working on a project that is a bit stuck with Blaze, and I would be willing to give a shot at implementing some quality of life stuff.

I think there are a few things that can be done fairly easily that would be great improvements:

  1. Update Blaze.With to use a dictionary of path -> ReactiveVar in addition to the single ReactiveVar for the entire context.
  2. Update Blaze.getView to cache 'with' data view inside of its corresponding child view after the first access. This makes it so that the instance does not need to constantly search up the view tree whenever it accesses its data context.
  3. Add Template.Instance getData([path]) method that accesses the cached data view directly and reactively gets context data
    • If a path is provided, it will use the path -> ReactiveVar dictionary to resolve the value so that it is only dependent on that path within the data context. Otherwise, it will use the whole context ReactiveVar (equivalent to Template.currentData except specified to the current template).
    • If the path does not yet exist in the context, a ReactiveVar will be created for it and depended on.
    • Spacebars data context lookups would access the context by key via getData
  4. (Breaking Change) Make 'this' context for helpers and events be the current Template instance.
    • This would make these blocks consistent with the onCreated/Rendered/Destroyed blocks and, most importantly, have the benefit of completely stopping the need for re-rendering the entire template when the data context changes by making 'this' a constant that never needs to be updated.
    • This is a breaking change, but shouldn't be too hard to migrate in most projects because of the ease of searching for helpers and events blocks. Essentially all 'this.prop' accesses would need to change to this.getData('prop').
  5. Add a 'computed' method to Blaze.Template that functions similarly to helpers with the following differences:
    • Computation functions would be autorun (so they take no parameters) and their values would be stored (similarly to the data context) in a dictionary of key -> ReactiveVar within the current Template instance view
    • We could implement a 'getComputed' method in Template.Instance that accesses the dictionary by key and returns the value of the corresponding ReactiveVar. It would also start the autorun for that computation if necessary.
    • So that they are accessible from Spacebars, for every computation initializated, we could create a corresponding function in __helpers that would just call this.getComputed(name). This means that computations and helpers share the same namespace, but I don't think that should be much of an issue.
    • This method would greatly reduce the need for caching the returns from helpers via #let blocks and should be more efficient than that, since it doesn't need to traverse to search the lexical scope.

I have already implemented most of these things in my own project by just overriding the default Blaze functions, but I think it would be worthwhile to implement them into the official codebase. In addition, the only breaking change would be the helper/event context, but again that wouldn't be too hard for most users to migrate anyway. Let me know what you think if you get the chance to look through this or if I've missed something/not explained clearly enough.

@filipenevola
Copy link
Collaborator

I'm closing this issue because it's too old.

If you think this issue is still relevant please open a new one.

Why? We need to pay attention to all the open items so we should keep opened only items where people are involved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants