Fork me on GitHub

Just updated our re-frame CodeMirror component in order to fix some interop issue with Parinfer,


@mccraigmccraig The only time I've seen performance problems was when either: 1. debug middleware is in place (doing very deep diffs) 2. large and complex objects are being sent through as props to components.


The reason you can get performance problems with point 2 is that = is used to compare the previous value in a prop to the new value in a prop, when determining if the component needs rerendering.


If those props are really big and differ only in some tiny aspect, then a lot of time can be spend doing the = to work out there is a difference.


This problem tends to get exacerbated by components which return a lot of hiccup. Ie. you are retuning lots of components, with lots of props (in your hiccup) and all of that will need to be checked by =


To further explain: imagine you were rendering a 19 by 19 "go" board. And that the board renderer component created hiccup for 361 sub components (19 x 19 grid) and to each child it passed a complex object which is the state of the whole board, from which the individual grid components were expected to extract what they needed. This arrangement might become slow because you have a parent component returning hiccup for 361 subcomponents (a lot of hiccup!) And for everyone of those components, Reagent must check the props to see if they are = to last time (in order to see if they need to be rerendered) and that comparison via = is deep, and has to be done 361 times.


Solutions to such cases are: - don't give the big complicated object to each of the 361 sub components and then ask them to extract what they need. Instead, give them the data they need and nothing more. That will make the = process faster. - return less hiccup in any one component.


But ultimately, the way to really track down what is going wrong is to use the OFFICIAL debugging technique:


See the four dominoes play out in the console.


Okay, I've been meaning to write this Wiki page for a while. I've taken what I wrote above and cleaned it up a bit:!-Performance-Problems


Thanks for the push simple_smile


@mikethompson: thanks for the kick, i started on implementing tracing...


what's the background to the macro restriction ? is it specific to reaction or are other macros going to be problematic too ? i tried surrounding a load of subs with trace-forms without changing reaction to make-reaction and it seemed to mostly work ok


do i need to worry about e.g. the macro i use to ensure .preventDefault gets called on event handlers ?


Clarvoyant does tracing by looking for defn and let etc, And tracing what goes in and out. reaction doesn't look like a function to it. So it won't trace them cleanly.


But, hey, start off simple and then add better trace as you get in


ah, ok, so it's not gonna break anything, it just won't work as well...


Which version of Reagent are you using?


If you are using 0.6.0-alpha try switching back to 0.5.2. Or visa versa. I'm not imaigning you'll see much difference, but I'm curious


Version 0.6.0-alpha uses an = check for Signal graph propagation, rather than identical?


(which affects reaction use)


currently on 0.5.1, though i'm due to try upgrading to 0.6.0-alpha in the next few days


@mikethompson: so is seeing stuff like er-webui.subs/fn_145110 [] (anonymous) in the trace likely the result of the reaction macro being used inside a sub-fn, rather than make-reaction (given that all the sub-fns have names) ?


(no need to answer that, i've confirmed it is)


Not sure. Remember that you'll see a particular order in the console. 1. An event handler fires (which updates app-db) 2. subscriptions fire (because of the change to app-db) 3. Views render (because of the changes in the subscriptions or props) That sequence happens for every dispatch. So between the colouring of the trace and you knowing what order things happen, you can normally figure out what you are looking at, even if you haven't gone to the trouble of maker-reaction


I'd identify one event which is being handled more slowly than you'd like. Just one. One that is easy to fire over and over (making it easy to explore). Then go about adding sufficient trace that you can see a complete and accurate view of the dominos.


i'm sold on the idea - i'll take the hit of a few hours now for the massively improved introspection


yeah the macro someone was proposing around make-reaction and giving names to re-frame anon functions is good 😄