Performance tuning a Reagent/Re-frame application

651 views
Skip to first unread message

Russell Dunphy

unread,
Jul 3, 2015, 10:42:36 AM7/3/15
to clojur...@googlegroups.com
Does anyone have any tips for performance tuning a reagent/re-frame application they can share? We're running into very slow rendering performance when changing pages on Firefox on Windows (ie sometimes several seconds) which, though still noticeably laggy, don't seem to be anywhere near as much of a problem in Chrome.

Unfortunately I can't share the codebase, but here's what we've been trying so far:

Using React.addons.Perf to identify components that take more data than they need as arguments - i.e their render function is called with changed data but they don't end up generating different markup. This has helped us reduce *re-render* performance, but doesn't help us much on initial page render, where is where our performance problems mainly lie.

Wrapping all our subscriptions using our own [custom register sub function](https://gist.github.com/rsslldnphy/5c937167380dd3442076) to track how many times each subscription is called, how long it takes etc, to reduce duplicated work and highlight inefficiences. This has helped us a bit, but slowness still remains.

To give a slightly better UX when moving between pages, we first update the app state with a key that causes a loading spinner to appear, then call reagent/flush to make sure it's rendered, *then* update the app state again to trigger the change to the new page. This still ends up being a bit jerky however (the gif often freezes while the page is rendering, or itself takes a while to appear) so any better suggestions would be very welcome.

Thanks in advance for your suggestions.

Russell

Colin Yates

unread,
Jul 3, 2015, 11:13:36 AM7/3/15
to clojur...@googlegroups.com
I notice (subjectively) that Chrome is generally a *lot* faster when running JS heavy apps than Firefox or, please no - IE<11.

A few tips, I am sure you are already doing:
 - only render what is needed, don’t use ‘hidden’ as they are still in the DOM
 - copy the rendered HTML from page1 and page2 into static HTML files and then add an "<a href” to transition between them - that removes all JS and leaves you with the faster you are going to get
 - identify the ‘real' performance bottlenecks; sure it may displease you, but will the users really care? What else could you be giving them if you didn’t have to work on this? This is a note to me more than you :).

HTH and if you find any other tips then shout loudly!

--
Note that posts from new members are moderated - please be patient with your first post.
---
You received this message because you are subscribed to the Google Groups "ClojureScript" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojurescrip...@googlegroups.com.
To post to this group, send email to clojur...@googlegroups.com.
Visit this group at http://groups.google.com/group/clojurescript.

Russell Dunphy

unread,
Jul 3, 2015, 12:06:58 PM7/3/15
to clojur...@googlegroups.com
Thanks Colin! The only one I'm not sure I follow is to "copy the rendered HTML from page1 and page2 into static HTML files". Is this for the special case where you don't have any dynamic content on the page? Or are you talking about rendering the generic structure of the page first, then loading in actual data?

Colin Yates

unread,
Jul 3, 2015, 12:12:45 PM7/3/15
to clojur...@googlegroups.com
Hi Russel, I often find my intuition as to where the problem is when it comes to performance is about as bad as my estimates (i.e. terrible) so I ruthlessly reduce the problem. In this case, is the performance problem in JS or simple rendering the DOM. One way to do that is use your app to render page 1 and inspect the HTML. Copy that HTML into a file called ‘page1.htm. Now use your app to transition to another page which is considered ‘slow’ and inspect the HTML. Copy that to a file called page2.htm. Now edit page1.htm and add a link to page2.htm. You now have a reduced problem set where there is absolutely no JS and is pure rendering.

Now, load page1.htm in the browser - how quick was that? Now click the transition button and wait for it to be rendered - how quick was that? It is sometimes surprising how long this takes, even without the overhead of JavaScript. At least now I am guided to whether the slog is in rendering the DOM (in which case chunking the DOM updates is one answer) or somewhere else.

That’s all I meant.

Russell Dunphy

unread,
Jul 3, 2015, 12:16:59 PM7/3/15
to clojur...@googlegroups.com
Ah, got you! That's a good idea, will give it a go, thanks.

Daniel Compton

unread,
Jul 4, 2015, 5:24:15 AM7/4/15
to clojur...@googlegroups.com
Are you using Re-com as well? That relies heavily on Flexbox which is only just starting to be optimised in Firefox. I think Firefox 38 from memory was where it started to get better performance, although still not as fast as Chrome. The other tip is to look at the rendering timeline and see which parts of code/browser events are taking the most time. I'm most familiar with Chrome's one, but I assume that Firefox has a similar one.
--
Daniel

Mike Thompson

unread,
Jul 4, 2015, 10:28:43 AM7/4/15
to clojur...@googlegroups.com

I'm wondering if clairvoyant might be useful to you in tracking this down. (I'm genuinely not sure, so just throwing it out there).

https://github.com/spellhouse/clairvoyant

Some time ago, I described the plan of attack for using clairvoyant with re-frame here:
https://github.com/Day8/re-frame/issues/34#issuecomment-82967304

The key thing about that plan is that it allows you can then observe the entire flow. If you wanted to, you could probably hack clairvoyant to give you performance profiling on each step as well.

In that github comment, it notes some problems. The good news is that two of them are fixed. We put in two PRs for clairvoyant:
1. one of them improves the display of functions in hiccup
2. one of them means you can switch off clairvoyant in production

I think the output would be interesting. You'd be able to see exactly what event handlers are running, what subscriptions are firing as a result, and what views are re-rendering. The results can sometimes be surprising.


Also, sorry to ask the obvious but: are you testing with devtools open? In some cases, that can massively slow things down, and can give you the impression of a dog slow app, when, in fact, with devtools closed speed is kinda acceptable. Just a thought.

Cheers,
Mike

Mike Thompson

unread,
Jul 4, 2015, 10:46:19 AM7/4/15
to clojur...@googlegroups.com
On Saturday, July 4, 2015 at 7:24:15 PM UTC+10, Daniel Compton wrote:
> Are you using Re-com as well? That relies heavily on Flexbox which is only just starting to be optimised in Firefox. I think Firefox 38 from memory was where it started to get better performance, although still not as fast as Chrome. The other tip is to look at the rendering timeline and see which parts of code/browser events are taking the most time. I'm most familiar with Chrome's one, but I assume that Firefox has a similar one.


Yeah, this is a good point. The flexbox implementation in Firefox v39 is fast (just released). But the previous v38 is dog slow if flexbox is used.

If you are using flexbox, then this could be a significant issue. Make sure you are using Firefox 39.

--
Mike

Mike Thompson

unread,
Jul 4, 2015, 10:48:28 AM7/4/15
to clojur...@googlegroups.com


Correction: version 38 fixed the slowness in flexbox (came out in May). It was the previous Firefox 37 which was dog slow.

--
Mike

Alan Moore

unread,
Jul 5, 2015, 8:33:44 PM7/5/15
to clojur...@googlegroups.com
Obviously using reagent/re-frame should minimize Dom updates but sometimes an app can behave differently than we think it should. Especially in an event driven system some operations may occur in different orders, etc, sometimes this can be caused by the inversion of control that comes with event oriented systems.

One biggie is Dom reflow so make sure your app isn't triggering some worst case in FF. Rendering a large table or sequence of flex-box all in one chunk is going to be way faster than one row/box at a time.

Good luck.

Alan

Russell Dunphy

unread,
Jul 6, 2015, 4:27:54 AM7/6/15
to clojur...@googlegroups.com
Thanks all for your suggestions - I am going to try them out and see what I can come up with, will post back here with results.

We're not using re-com as unfortunately our users will often be in relatively locked down IT environments without the latest versions of browsers. And I can confirm that we don't have devtools open while experiencing the poor performance ;-)

Russell

Reply all
Reply to author
Forward
0 new messages