Fork me on GitHub
#graalvm
<
2021-10-13
>
Asko Nōmm04:10:33

Does anyone here have any tips of how to reduce the final binary size? It’s not too bad by any means, but if possible I’d like to shave off some bytes 🙂

borkdude06:10:50

Yes, there are a few things you can do. What is the size now?

Asko Nōmm13:10:53

Between 25-35mb usually, depending on the target OS (MacOS is usually larger than Linux)

borkdude13:10:28

Is this for your shh script?

Asko Nōmm14:10:38

Yup, as well as another one of mine (https://github.com/askonomm/babe) which actually has a lot more code, and dependencies, and for some odd reason produces smaller binaries haha

borkdude15:10:31

@asko304 I would recommend bisecting. Start with a small subset of your program. Compile. Inspect size. Add a little more. Until you discover what triggers a substantial increase in size and then report back

Asko Nōmm16:10:03

Good idea! I’ll do just that. Thank you 🙂

borkdude13:10:22

Something that could help is direct linking, although the effect is not always visible

borkdude13:10:26

The smallest binary I typically get for clojure is 8 mb or so. With SCI 11 mb or so. But some libraries (like pprint) can trigger much more because of some dynamic stuff that graalvm can't reason about very well. As for your script, I don't see anything suspicious.

👍 1
Karol Wójcik13:10:01

Hmm typically i get 11-12 Mb. For Retailic API with a lot of deps I had 21MB but it’s still reasonable.

borkdude13:10:53

21mb is really small for a web application with a lot of deps: are you sure this is not the .zip size? :)

Karol Wójcik13:10:57

:rolling_on_the_floor_laughing: right it's a zip size

borkdude13:10:34

ok then the real size is probably x3 or x4 ;)

borkdude13:10:03

it's actually the size of bb right now: around 21mb zipped

borkdude13:10:26

clj-kondo is 38mb unzipped (around 1/2 the size of bb)

ericdallo16:10:18

last time I checked there was issues with macos big sur

Asko Nōmm16:10:34

@ericdallo Just tried UPX and it managed to turn a 30mb binary into 7mb! But, it also changes the running user into “runner” and not the actual user name, thus me getting (System/getProperty "user.home") breaks. At least on Mac OS, I do not have a Linux to test with.

ericdallo16:10:34

Oh, good to know, actually, clojure-lsp also uses (System/getProperty "user.home") :thinking_face:

ericdallo16:10:43

I can test later today if that happens for linux as well

Asko Nōmm16:10:18

Actually, ignore that. Seems to by caused by something else entirely 😕

Asko Nōmm16:10:46

I have a feeling it is Github Actions MacOS build, and Graal VM that turns home directory into /Users/runner, because when I run the same exact build locally on my Mac it is totally fine.

ericdallo16:10:34

yeah, runner is indeed the user github actions use

Asko Nōmm16:10:42

Perhaps I should instead opt for clojure.java.shell to get the user directory instead of System/getProperty?

Asko Nōmm16:10:54

Because it seems with getProperty it will get hardcoded in the binary

borkdude17:10:27

Note that upx is basically zip/unzip at runtime and in memory and induces some startup time (250ms or so): I personally don't think it's worth the extra runtime penalty vs how much extra disk space it takes.

👍 2
Asko Nōmm19:10:33

The startup time of upx depends on the how fast the computer can decompress the archive, which depends on disk read/write speed or CPU or both? If so it would indicate that the startup time will get lesser with more modern machines, assuming that the original binary size stays the same.

Asko Nōmm19:10:19

I also measured the performance difference just now on a M1 Macbook Pro with 8GB ram: • Without upx: 0.10s • With upx: 0.23s 0.13s slower, for a binary that is 30mb in size originally.

borkdude17:10:17

@asko304 You should not evaluate System properties on the top level if you want to capture those from the user's runtime environment. Instead, wrap it in a delay or function. Else you'll be seeing compile time values.

Asko Nōmm17:10:45

I just realized that actually! def defines instantly whether defn only on-call, and was in the process of testing this.

Asko Nōmm17:10:12

Rookie mistakes hehe

borkdude17:10:50

This is the direct result of --initialize-at-build-time which cannot be avoided for Clojure currently. It's not a rookie mistake, it's just a difference with how you normally run Clojure on the JVM. Wrapping in delays is a necessary tweak for this.