This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-10-13
Channels
- # aleph (8)
- # announcements (3)
- # beginners (36)
- # calva (1)
- # cider (1)
- # circleci (3)
- # clj-kondo (9)
- # cljdoc (58)
- # clojars (7)
- # clojure (70)
- # clojure-europe (13)
- # clojure-japan (1)
- # clojure-nl (8)
- # clojure-russia (2)
- # clojure-uk (7)
- # clojuredesign-podcast (4)
- # clojurescript (67)
- # clojureverse-ops (14)
- # cursive (6)
- # data-science (1)
- # datahike (3)
- # datomic (6)
- # docker (1)
- # events (2)
- # figwheel-main (9)
- # fulcro (4)
- # graalvm (33)
- # graphql (8)
- # helix (1)
- # jobs (1)
- # leiningen (3)
- # lsp (39)
- # malli (9)
- # minecraft (31)
- # nextjournal (7)
- # off-topic (6)
- # portal (22)
- # re-frame (5)
- # reitit (5)
- # remote-jobs (1)
- # shadow-cljs (55)
- # sql (22)
- # tools-build (3)
- # tools-deps (4)
- # xtdb (6)
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 🙂
Between 25-35mb usually, depending on the target OS (MacOS is usually larger than Linux)
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
@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
Something that could help is direct linking, although the effect is not always visible
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.
Hmm typically i get 11-12 Mb. For Retailic API with a lot of deps I had 21MB but it’s still reasonable.
21mb is really small for a web application with a lot of deps: are you sure this is not the .zip size? :)
:rolling_on_the_floor_laughing: right it's a zip size
You can use UPX as well: https://github.com/clojure-lsp/clojure-lsp/blob/master/.github/workflows/release.yml#L81-L84 Clojure-lsp uses it for linux and windows
@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.
Oh, good to know, actually, clojure-lsp also uses (System/getProperty "user.home")
:thinking_face:
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.
Perhaps I should instead opt for clojure.java.shell
to get the user directory instead of System/getProperty
?
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.
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.
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.
@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.
I just realized that actually! def
defines instantly whether defn
only on-call, and was in the process of testing this.