lynaghk / cljs-react-perf

Performance experiments w/ CLJS React libraries and techniques.
40 stars 1 forks source link

Performance suggestion #2

Closed thheller closed 7 years ago

thheller commented 7 years ago

Didn't have time to look at your full benchmark setup but you are missing two very important compiler options in your build.clj. In anything performance sensitive you want to have :static-fns true and :optimize-constants true.

Without those I get

app-2
94 ± 16

with

app-2
69 ± 17

I suppose that is a gain, don't exactly sure what the numbers stand for.

Might have some more suggestions tomorrow.

lynaghk commented 7 years ago

Thanks for the note! I didn't know about either of those compiler options.

It looks like both :optimize-constants and :static-fns both default to true under advanced optimizations, which is something I need to setup (#3).

A bigger question for me would be: What are use cases where you'd want :simple optimizations to get faster, but where you don't want to use :advanced optimizations?

The only case I can think of is that you're terrified about missing an externs declaration and breaking your app in production. (Not that this has ever happened to me...) If that's the only case, perhaps instead of trying to make :simple faster, we can make :advanced safer by running it without variable renaming.

That the Closure library has a VariableRenamingPolicy enum suggests that it's possible, though I don't know if this can be leveraged from the cljs compiler api.

Thoughts?

thheller commented 7 years ago

:advanced mode is about much more than just renaming some vars. If you turn off everything that doesn't work properly without externs you get :simple. You really can't do much more without.

:optimize-constants is the most important since it will result in my.ns.some_fn($cljs$core$cst$foo) with the keyword only being allocated once as opposed to my.ns.some_fn(new cljs.core.Keyword(...)) allocating it over and over again.

So with that and :static-fns you get close enough performance wise.

Running benchmarks without these will produce misleading results since allocating keywords in a loop may cause many extra GC pauses.

If you really can ensure perfect externs though :advanced will be far better.

lynaghk commented 7 years ago

Got it, thanks for the info!

What's the downside of :optimize-constaints? Is the only reason it's off by default because it leads to longer compilation times?

Re: GC pauses, I'm looking into a way to disable GC during the benchmarks, since that seems to be the most straightforward way to measure memory usage (i.e., allocations per re-render).

thheller commented 7 years ago

:optimize-constants does not work with incremental compilation.

I actually wasn't aware it was enabled for :advanced automatically, it should probably be for :simple and :whitespace as well.

No idea if you can disable GC. Given how much React and the wrappers allocate that might not actually work too well too. Also wouldn't resemble real-world situations.

thheller commented 7 years ago

You might want to look at a setup like this: https://github.com/krausest/js-framework-benchmark http://www.stefankrause.net/wp/?p=218 http://www.stefankrause.net/wp/?p=191 http://www.stefankrause.net/wp/?p=283 http://www.stefankrause.net/wp/?p=301 http://www.stefankrause.net/wp/?p=316 http://www.stefankrause.net/wp/?p=392

lynaghk commented 7 years ago

Thanks for links, someone else pointed me towards that project.

Can you clarify what you meant by this:

:advanced mode is about much more than just renaming some vars. If you turn off everything that doesn't work properly without externs you get :simple.

My understanding from the Closure docs is that :advanced will also do dead code elimination and inlining, which aren't obviously (to me) related to renaming.

In any event, I'll do some experiments later today and see what shakes out. Thanks!

thheller commented 7 years ago

http://closuretools.blogspot.de/2011/01/property-by-any-other-name-part-3.html