Fork me on GitHub
#reagent
<
2021-11-15
>
mauricio.szabo15:11:44

Hi - I was looking for tips on optimizations. I'm currently working on a really complicated and customizable rendering for EDN objects, and I'm having HUGE performance problems. So I benchmarked a while, and to isolate most cases I decided to use render-to-string to see the bottlenecks. It all points to my rendering functions, lots of time on wrap-funs and as-element. Is there a way to either avoid these calls, or to benchmark further what's wrong?

Lu16:11:09

Are you doing things in loops and/or recursively when rendering you components?

Lu16:11:33

I wrote this article about cljs performance not too long ago.. I guess see if it helps: https://www.juxt.pro/blog/clojurescript-app-performance.

mauricio.szabo17:11:06

My problem is not exactly on ClojureScript, but on my react/reagent code. There's little "logic", but lots of cursors, r/atom, etc...

Lu17:11:33

Could you share some code?

mauricio.szabo18:11:51

Sure - it's on REPL-Tooling: https://gitlab.com/clj-editors/repl-tooling/-/blob/rethink-rendering/src/repl_tooling/editor_integration/renderer/edn.cljs As I'm benchmarking, I believe it's because I'm returning an anonymous function on every possible component. Don't know if it makes sense

mauricio.szabo18:11:31

Well, seems that when I removed the anon function it indeed became faster. I'll check if that's the trouble (it's hard to debug performance problems in old Electron apps 😞)

Lu21:11:08

I will have a better look in a bit! I might have spotted something

mauricio.szabo01:11:26

Wonderful! If you need to test anything, it's easy to run the project: just clone, run ./scripts/watch, and when it compiles run npm start. This will open an Electron with devcards on it, look for edn_test. I'm also trying things on my side here 🙂

mauricio.szabo03:11:24

So, just to point that I found some os the hotspot - most are related to r/cursor. I'm currently creating cursors indiscriminately. I'll probably have to slow down a little bit on that part

mauricio.szabo03:11:52

I also am caching now some duplicated elements, and pré-creating them with r/as-element

mauricio.szabo02:11:55

@lucio, thanks for listening. After a lot of tries (and frustration on how bad the profiling tools in devtools are) I found the problem: I'm just creating too much sub-elements in my code. I migrated everything to pure React, with JS interop, and I was still seeing the rendering problem. So I decided on another approach: to "combine" elements that are compatible (for example, instead of [:div [:div "a"] [:div "b"]], I can just write [:div [:div "a" "b"]]). I wrote a code to do this combination, and now my rendering is running on 300ms (instead of 6s that was originally running). I'll probably write a post about it. Also, I have to be thankful for Reagent to use hiccup - without it, I would NEVER be able to combine these elements automatically!

mauricio.szabo02:11:55

@lucio, thanks for listening. After a lot of tries (and frustration on how bad the profiling tools in devtools are) I found the problem: I'm just creating too much sub-elements in my code. I migrated everything to pure React, with JS interop, and I was still seeing the rendering problem. So I decided on another approach: to "combine" elements that are compatible (for example, instead of [:div [:div "a"] [:div "b"]], I can just write [:div [:div "a" "b"]]). I wrote a code to do this combination, and now my rendering is running on 300ms (instead of 6s that was originally running). I'll probably write a post about it. Also, I have to be thankful for Reagent to use hiccup - without it, I would NEVER be able to combine these elements automatically!