Fork me on GitHub
#fulcro
<
2022-12-20
>
Hukka16:12:33

Any better ways to measure the time a mutation takes than to use the browser profiler? Any way to fire a callback when fulcro has finished rendering after the db changed?

Hukka16:12:06

Hmm. Perhaps checking the clock in another transaction, that the first one fires with :after-render? true ?

Hukka16:12:01

Could be called like (transact! this [(measurement-start) (transaction-to-measure)]) and then measurement-start takes note of the time, queues measurement-end after the render, and that in turn will again check the time and print the result

Hukka17:12:40

Heh, seems to work exactly

tony.kay17:12:54

Timing things is a fun task in browsers. Remember that in dev mode there is a lot of stuff “billed to” the mutation that isn’t your code or even production-necessary code: serializing new stuff to Inspect, logging stuff, React is in dev mode.

tony.kay17:12:35

Also, which transaction alg you’re using. The sync transaction support will have a MUCH lower overall latency from call to transact to the render result.

Hukka18:12:19

Yeah, inspect takes a heavy toll, when a lot of data is put into the db, but also really simple to turn off while doing that. Wasn't even aware that transaction can be tweaked. Had read only about the renderers

Hukka18:12:28

Found it in chapter 25, gotta read that

tony.kay18:12:38

everything can be tweaked 😛

tony.kay18:12:54

but most of this kind of tweaking is usually premature

tony.kay18:12:10

once you make a prod build and measure, it’s usually quite fast

Hukka18:12:18

I already got pretty happy results, though I admit that there was nothing very surprising. Biggest surprise was that putting derived state into the db to avoid calculating it five times, actually resulted to even better than five time speedup. I don't know if the GC got happier, or what was going on

tony.kay18:12:39

This is a useful shadow cljs config:

:performance-dev {:target           :browser
                                       :output-dir       "resources/public/js/main"
                                       :asset-path       "/js/main"
                                       :js-options       {:ignore-asset-requires true
                                                          :resolve               {"react-dom" {:target  :npm
                                                                                               :require "react-dom/cjs/react-dom.production.min.js"}
                                                                                  "react"     {:target  :npm
                                                                                               :require "react/cjs/react.production.min.js"}}}
                                       :modules          {:app {:entries [app.client]}}
                                       :devtools         {:after-load app.client/refresh}
                                       :compiler-options {:closure-defines {goog.DEBUG false}
                                                          :external-config {:fulcro {:html-source-annotations? true}}}}
(modify the modules and devtools)

Hukka18:12:44

Also, the browser profiler is pretty awful compared to what we have on JVM side

tony.kay18:12:57

it gives you hot code reload with prod performance

Hukka18:12:40

And the measurements didn't stay stable over different compilations with same code, changing with tens of percents, while somewhat stable as long as shadow didn't redo anything

tony.kay18:12:24

I’ve had pretty good luck with chrome profiler using that config…at least for finding the hot spots

Hukka18:12:48

It's workable. Just wish there was better tooling to limit the profile to relevant parts. Like you can do with the flamegraph page clj-async-profiler gives

Hukka18:12:19

That config is neat, I'll steal it

Hukka18:12:16

Some parts I don't recognize, like html-source-annotations. More googling to do

Hukka18:12:28

Hm, can't find anything even on :external-config. Not on shadow's nor on clojurescript compilers pages. And google is singularly useless, finding anything that is even close to those. What does that do?

Hukka19:12:15

Found the relevant parts, so that's a place where people just seem to put stuff for their own configuration during cljs compilation, and then where fulcro uses that in dom.clj. Just need to figure out what it means in this case 😉

tony.kay21:12:22

It adds the namespace and line number that the dom element was written from

tony.kay21:12:39

so you can inspect elements in the Chrome devtools (normal HTML elements) and they’ll have info about where they are in the source

tony.kay21:12:51

only works if you trigger the macro (which means nil or a map for props)