Hacker News new | ask | show | jobs
by Eridrus 4000 days ago
Dart makes a decent argument for a smarter compiler. They've implemented "Tree Shaking" in their compiler: essentially cross-library dead code elimination.

This would probably be quite tricky in Java land where reflection does add new entry points, but it could be used to solve the problem of "I only need this one function from this library, don't compile in anything else".

I was personally quite surprised when I ported from code from Node to Java/Groovy and the resulting shaded JAR was > 70MB, I think at some point it peaked above 110MB. I don't know what I changed, but it's down to 35MB now. But the code that we've written in house on that codebase boils down to 1MB. But besides figuring out that I don't want to make local builds I scp to staging (because scp is terrible), these numbers are all completely equivalent for writing server-side software that runs on dedicated machines.

We could certainly make it more efficient, but there's exactly zero business case for it.

2 comments

You can only tree-shake a whole program compilation, but then you cannot use compilation units, modules and modularity efficiently. You have to choose one or the other.

Every normal compiler implements simple (i.e. module level) dead-code elimination already.

EDIT: Of course you could use static libs, which does pull in only used symbols, but then you cannot share them across apps and update independently.

I implemented a tree shaker for my lisp and was very happy with it, esp. for delivery. Like Go does it nowadays.

Right, I guess I wasn't clear, this was a shaded/fat jar, so it had all its dependencies included statically.

I feel like our computing infrastructure has gotten to the point that dynamically linked libraries are no longer a good choice. I think dynamic linking has only caused us problems at work (devs install Node deps on the staging server, forget to tell ops, service crashes when deployed in prod), and the memory/disk/transfer overhead are practically irrelevant at this point. The only remaining reason to have dynamic libs is the idea that they can be updated without help from upstream, but that really only works if the software is compatible with the latest libraries, which isn't always true.

Supposedly ProGuard has some cross-module dead code elimination for JARs, but I haven't tried it: http://proguard.sourceforge.net/

> I ported from code from Node to Java/Groovy

How much of that was Java's fault and how much Groovy's, I wonder?

Given my own code was only 1MB total, neither. 97% of the size was from external dependencies. FWIW, it was a "shaded" jar that had all its dependencies linked in statically.