Fork me on GitHub
#graalvm
<
2021-11-21
>
igrishaev11:11:55

Hi! Can anyone give me some tips on how to reduce the size of the binary file? I'm compiling a simple CLI Clojure project that only depends on cheshire and clj-http-lite. The size of the file is 45-46Mb.

nenadalm12:11:54

If you don't mind slowing down your program a bit, you can compress it using upx: https://upx.github.io/

igrishaev11:11:56

which is tolerantly, but still worths to be reduced

igrishaev12:11:50

I've tried to replace clj-http-lite with a primitive Clojure wrapper on top of http://java.net.http.HttpClient, but the size didn't change

igrishaev12:11:06

nor when I swap cheshire with clojure.data.json

borkdude12:11:25

@igrishaev you can get this down to probably 15 mb. usually this inflation occurs when you're dynamically requiring vars somewhere

borkdude12:11:34

so it kind of depends on your coding style

borkdude12:11:01

if your code is public then I could try to pin it down

borkdude12:11:42

having said this, babashka also contains cheshire and is compatible with clj-http-lite (but also has other http clients on board) so you can maybe also run it with that already, depending on your use case

borkdude12:11:53

@igrishaev as the author of etaoin, you might also be interested in seeing what I did to make it run with babashka: https://github.com/babashka/pod-babashka-etaoin

igrishaev12:11:05

thanks, @borkdude! The code is not public yet, I need to check if I can share it

igrishaev12:11:34

actually, I don't require any vars, but read a resource file in runtime

borkdude12:11:06

@igrishaev thanks for inviting me to the repo. I see your'e using clojure.pprint and that uses vars dynamically.

borkdude12:11:23

this is likely the culprit of the image size bloat. try without pprint for now. I know a workaround for this

igrishaev13:11:43

Yes I saw this ticket, and also had some compilation errors with clojure < 1.10.2

borkdude13:11:44

yes, see topic of this channel. just use the newest clojure

igrishaev13:11:18

wow, without pprint, the size is 28M

borkdude13:11:22

I hope the patch will make it into Clojure, that will make clojure.pprint better to use with graalvm

igrishaev13:11:24

which is something close to golang

borkdude13:11:34

You can fix this in user space though with alter-var-root

borkdude13:11:41

The smallest image I can get is around 10mb or so

borkdude13:11:53

with Clojure that is

igrishaev13:11:38

I wonder if it's possible to reduce the size even more

borkdude13:11:02

@igrishaev I found that when using httpkit as the client, this is only takes 1.5mb or so

borkdude13:11:06

even including the webserver :)

igrishaev13:11:05

oh, that's good to know. Will try it

igrishaev13:11:42

also, is it ok to embed resources into the binary file?

igrishaev13:11:11

I have a huge JSON file. There is an option to generate a static namespace file before compilation

igrishaev13:11:02

say, to produce a .clj file with one var (def my-data ...) from that json

borkdude13:11:51

yes, that is ok

borkdude13:11:21

you can also read the JSON from the resource in the image though

borkdude13:11:34

then you have to configure it to include that resource

igrishaev13:11:41

yes, I did it

igrishaev13:11:01

I just thought that maybe it brings some runtime shananigence

borkdude13:11:01

but if you have the compiled namespace in the image then you don't need to include the JSON anymore right

borkdude13:11:31

What I mean: you can make (slurp`(io/resource "my-json.json")` )work at runtime in the image

borkdude13:11:35

but this requires extra config

igrishaev13:11:04

right, I have this in my command: -H:IncludeResources='.*my-file.json$' \

borkdude13:11:28

yeah, but if you do the processing of this json at compile time (a top level def) then you don't need this

igrishaev13:11:00

yep, that also be faster on startup