[ClojureScript] Re: Seeking advice for a reducing the size of compiled scripts

2018-12-21 Thread Tom Connors
Thanks Antonin, I wasn't aware that top-level data defs are universally bad 
for DCE.

Yuri, I think you're right in general, but my application can be compiled 
with particular features excluded so multimethods are problematic even in 
my application code. And I've found that with re-frame applications unless 
I'm very disciplined about removing dead code I end up with unused event 
handlers - I'm sure some people experience the same with multimethods. 
That's an easy problem to solve, but in closed systems like applications 
I've always found that static dispatch with a big `case` or something 
similar works fine.

-- 
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 clojurescript+unsubscr...@googlegroups.com.
To post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: Seeking advice for a reducing the size of compiled scripts

2018-12-21 Thread Yuri Govorushchenko
> Avoid multimethods and other global registries like re-frame. These 
thwart DCE because there’s no way to know at compile time that a specific 
method/handler is never used.

Isn't this advice only applicable to libraries which have a lot of 
multimethods in the implementation? If the project codebase itself (not the 
libraries) contains multimethods then I suppose they are all needed in 
production potentially and thus should never be eliminated.

-- 
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 clojurescript+unsubscr...@googlegroups.com.
To post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: Seeking advice for a reducing the size of compiled scripts

2018-12-21 Thread Antonin Hildebrand
Here are some of my findings when trying to make cljs-devtools library more 
DCE friendly:
https://github.com/binaryage/cljs-devtools/issues/37#issuecomment-293575471

Not sure if they still apply today, the post is from Apr 2017.

good luck,
Antonin 

On Thursday, December 20, 2018 at 5:18:34 PM UTC+1, Tom Connors wrote:
>
> At work we use clojurescript to implement a front-end with minified and 
> gzipped assets coming in at around 170KB. If I can’t reduce that 
> substantially I’ll probably have to rewrite in javascript. I’m posting to 
> share some ideas I have for reducing the size of the script and to ask for 
> any additional techniques others have used to get smaller scripts.
>
> Things I can do right now:
>
>- Measure the impact of every library: I’ve found that transit adds 
>about 12KB gzipped and core.async adds even more (probably variable due to 
>the transformations performed by the go macro). Reagent is 
>surprisingly light - about 4KB. I’m using preact instead of react, so that 
>lib is an almost negligible 3KB. Importantly, I’ve found that some APIs 
>provided by google closure can have surprising impacts on script size. 
>Don’t use goog.xhr - do direct interop for http requests. 
>- Avoid multimethods and other global registries like re-frame. These 
>thwart DCE because there’s no way to know at compile time that a specific 
>method/handler is never used. 
>- Remove unnecessary parts of data structures. If you have a literal 
>vector of maps where each map has a key or two that isn’t used by code 
>(perhaps it’s just information for developers), those unused keys won’t be 
>DCE’d 
>- Make use of goog defines to get rid of code paths that you can 
>determine to be unnecessary at compile time. 
>- Avoid using apply for functions that implement a lot of different 
>arities. The clourescript compiler tends to be really smart about this - 
> if 
>you implement 1, 2, and 3 arity versions of a function and only call the 
>two arity one, the 1 and 3 arity versions can get DCE’d. If you use 
>apply, however, all the arities end up in the script. 
>- Do a second round of minification with uglify or some other 
>minifier. I haven’t tested this in a while, but when I did last time it 
>saved a KB or two. At least it compresses the Math.imul definition at the 
>top of the script. 
>
> Aside from dropping heavy libraries, those are all incremental changes. In 
> order to get really substantial size savings, I think changes would need to 
> be made to clojurescript. I have no idea about the feasibility of these 
> things.
>
>- (ideally) automatically (but probably based on configuration) remove 
>unused methods of type definitions. For example, cljs.core.UUID implements 
>the equiv method of Object. Suppose we know at compile time that we 
>will construct UUIDs but not compare them with anything. It would be great 
>to be able to remove that method’s definition. I doubt this is possible 
>without a static type system, but I wonder whether there is some way to 
>make this configurable that wouldn’t lead to an explosion of configuration 
>options and inscrutable errors. 
>- Some functions implement multiple arities for dispatch performance. 
>I would like to be able to say “I accept the performance hit in exchange 
>for only implementing one arity of this function”. For instance, 
>partial implements multiple arities of its own args and of the 
>function it returns. This could be reduced down to (defn partial [f & 
> more] 
>(fn [& args] (apply f (concat more args if we cared more about script 
>size than runtime performance. 
>
> Any other ideas?
> ​
>
>

-- 
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 clojurescript+unsubscr...@googlegroups.com.
To post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: Seeking advice for a reducing the size of compiled scripts

2018-12-21 Thread Tom Connors
Nathan, yes, I'm using advanced compilation, thanks.

Thomas, my concern with using :modules is polluting the global scope. We 
deliver code for other companies to run on their websites and putting 
multiple variables on the global scope is too risky. That being said, maybe 
I can wrap each module's code in a function that aliases `window` - I 
haven't explored that avenue much.
When I last looked at where the KBs come from 
using https://github.com/danvk/source-map-explorer there were not many 
surprises - a lot of the size came from closure's libs, clojurescript.core, 
and my application code. The only third party libs I'm still using are 
preact and reagent.
I agree about cljs being competitive and providing something much better 
than what we get with plain js. Sadly, telling customers that our script is 
bigger because we use a better programming language doesn't always satisfy 
them. ¯\_(ツ)_/¯
Thanks for the suggestions.

-- 
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 clojurescript+unsubscr...@googlegroups.com.
To post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.


[ClojureScript] Re: Seeking advice for a reducing the size of compiled scripts

2018-12-21 Thread Thomas Heller
Did you look into using Code Splitting aka :modules to reduce the size of 
the initial download?

Did you check where your 170KB actually come from? Including things like 
cljs.pprint can add quite a bit and isn't commonly used in production 
builds but can't be DCE'd (yet), similarly other namespaces can bloat the 
final output just by being required. Modifying the compiler to remove 
certain signatures or other tweaks is likely asking for trouble and there 
is currently no option to do this.

With that being said CLJS output is generally very competitive or even 
smaller than comparable JS builds if you account for what you are actually 
using. The Closure Library is also built for maximum compatibility which is 
less relevant these days but can still save hours of debugging if you care 
about supporting older systems, at the cost of a few extra bytes. Don't 
just compare with vanilla JS without immutable datastructures, sane 
equality semantics and so on.

Cheers,
Thomas


On Thursday, December 20, 2018 at 5:18:34 PM UTC+1, Tom Connors wrote:
>
> At work we use clojurescript to implement a front-end with minified and 
> gzipped assets coming in at around 170KB. If I can’t reduce that 
> substantially I’ll probably have to rewrite in javascript. I’m posting to 
> share some ideas I have for reducing the size of the script and to ask for 
> any additional techniques others have used to get smaller scripts.
>
> Things I can do right now:
>
>- Measure the impact of every library: I’ve found that transit adds 
>about 12KB gzipped and core.async adds even more (probably variable due to 
>the transformations performed by the go macro). Reagent is 
>surprisingly light - about 4KB. I’m using preact instead of react, so that 
>lib is an almost negligible 3KB. Importantly, I’ve found that some APIs 
>provided by google closure can have surprising impacts on script size. 
>Don’t use goog.xhr - do direct interop for http requests. 
>- Avoid multimethods and other global registries like re-frame. These 
>thwart DCE because there’s no way to know at compile time that a specific 
>method/handler is never used. 
>- Remove unnecessary parts of data structures. If you have a literal 
>vector of maps where each map has a key or two that isn’t used by code 
>(perhaps it’s just information for developers), those unused keys won’t be 
>DCE’d 
>- Make use of goog defines to get rid of code paths that you can 
>determine to be unnecessary at compile time. 
>- Avoid using apply for functions that implement a lot of different 
>arities. The clourescript compiler tends to be really smart about this - 
> if 
>you implement 1, 2, and 3 arity versions of a function and only call the 
>two arity one, the 1 and 3 arity versions can get DCE’d. If you use 
>apply, however, all the arities end up in the script. 
>- Do a second round of minification with uglify or some other 
>minifier. I haven’t tested this in a while, but when I did last time it 
>saved a KB or two. At least it compresses the Math.imul definition at the 
>top of the script. 
>
> Aside from dropping heavy libraries, those are all incremental changes. In 
> order to get really substantial size savings, I think changes would need to 
> be made to clojurescript. I have no idea about the feasibility of these 
> things.
>
>- (ideally) automatically (but probably based on configuration) remove 
>unused methods of type definitions. For example, cljs.core.UUID implements 
>the equiv method of Object. Suppose we know at compile time that we 
>will construct UUIDs but not compare them with anything. It would be great 
>to be able to remove that method’s definition. I doubt this is possible 
>without a static type system, but I wonder whether there is some way to 
>make this configurable that wouldn’t lead to an explosion of configuration 
>options and inscrutable errors. 
>- Some functions implement multiple arities for dispatch performance. 
>I would like to be able to say “I accept the performance hit in exchange 
>for only implementing one arity of this function”. For instance, 
>partial implements multiple arities of its own args and of the 
>function it returns. This could be reduced down to (defn partial [f & 
> more] 
>(fn [& args] (apply f (concat more args if we cared more about script 
>size than runtime performance. 
>
> Any other ideas?
> ​
>
>

-- 
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 clojurescript+unsubscr...@googlegroups.com.
To post to this group, send email to clojurescript@googlegroups.com.
Visit this group at https://groups.google.com/group/clojurescript.