graalvm

Discuss GraalVM related topics. Use clojure 1.10.2 or newer for all new projects. Contribute to https://github.com/clj-easy/graal-docs and https://github.com/BrunoBonacci/graalvm-clojure. GraalVM slack: https://www.graalvm.org/slack-invitation/.
ericdallo 2021-02-12T12:42:09.165100Z

:graal-vm: New GraalVM release: https://www.graalvm.org/release-notes/21_0/#21002, with just bug fixes on the updater tool

ericdallo 2021-02-12T13:09:53.165900Z

Did anyone try this https://upx.github.io/ to decrease the native image size?

borkdude 2021-02-12T13:24:09.166600Z

yes. it works, but it will inccrease startup somewhat (like it adds 100-200ms or so)

borkdude 2021-02-12T13:24:48.167200Z

which for babashka / clj-kondo I did not find acceptable, but for clojure-lsp I can see that being acceptable since it's a long running server

ericdallo 2021-02-12T13:25:45.167800Z

I see, do you know why it increase the startup? it's kind of curious :thinking_face:

borkdude 2021-02-12T13:26:01.168300Z

because it has to unzip stuff at startup

ericdallo 2021-02-12T13:26:10.168500Z

hum, make sense

ericdallo 2021-02-12T13:26:46.169600Z

nice, I'll give a try and try some benchmarks to see if it works nice for clojure-lsp

borkdude 2021-02-12T13:26:49.169700Z

most people have indicated in the babashka survey 2020/11 that binary size wasn't a huge priority for them

ericdallo 2021-02-12T13:27:20.170500Z

yeah, babashka is really small, that's so cool

ericdallo 2021-02-12T13:27:31.170900Z

but clojure-lsp is with 118 mb 😞

borkdude 2021-02-12T13:27:36.171100Z

I think what matters most is network size, so if the release file is a zip, you save network bandwidth, but on the machine the unzipped size doesn't matter much

borkdude 2021-02-12T13:27:57.171600Z

babashka is now 70-80mb, but zipped 20mb or so

ericdallo 2021-02-12T13:28:02.171800Z

I agree, I do the same with clojure-lsp, the zip is about 30 mb

borkdude 2021-02-12T13:28:52.172600Z

I have sometimes found that having a runtime require or resolve in your code can bloat the binary with 30 mb or so. so I usually hunt that spot down and get rid of it using alter-var-root or whatnot

borkdude 2021-02-12T13:29:25.172900Z

build-time (top-level or macro-expansion time) require/resolve is ok though

ericdallo 2021-02-12T13:32:15.173800Z

oh, good to know! I think the only require clojure-lsp has at runtime is via dynaload but only require nrepl if in a debug profile (not graalvm)

borkdude 2021-02-12T13:33:18.174100Z

that dynaload could trigger the bloat still though

borkdude 2021-02-12T13:33:47.174400Z

this is why I've made a graalvm variation of this here: https://github.com/borkdude/dynaload

ericdallo 2021-02-12T13:34:23.174900Z

you mean the borkdude.dynaload.aot variable?

borkdude 2021-02-12T13:34:40.175300Z

by setting the java property borkdude.dynaload.aot=true when compiling natively, it will yield smaller binaries

ericdallo 2021-02-12T13:34:52.175500Z

I think I forgot to do that 😅 thanks!

borkdude 2021-02-12T13:36:38.175800Z

so in the uberjar you will need to do that already

borkdude 2021-02-12T13:37:08.176100Z

and also during graalvm compilation

ericdallo 2021-02-12T13:38:00.176600Z

Got it, will try this later, hope it'll decrease the size

borkdude 2021-02-12T13:38:17.177Z

to be sure, put a (println (System/getProperty "borkdude.dynaload.aot")) at the top level in your code

ericdallo 2021-02-12T13:38:47.177300Z

yeah, I'll certainly do that hahah

ericdallo 2021-02-12T16:11:07.177800Z

Do you have an example of a project setting that variable to true @borkdude?

borkdude 2021-02-13T08:07:44.185400Z

These properties are not part of the runtime, only during build

borkdude 2021-02-13T08:08:18.186400Z

So you should put them on the top level and watch if they are printed during compilation

borkdude 2021-02-13T08:08:36.187Z

Of both Clojure and GraalVM

ericdallo 2021-02-13T14:12:02.187200Z

Oh, now it makes sense!

ericdallo 2021-02-13T16:01:31.190200Z

So, the clojure.compiler.direct-linking was correctly configured, it was just missing the dynaload config that i"ll add now 🙂

borkdude 2021-02-13T16:02:02.190400Z

🎉

ericdallo 2021-02-13T16:12:39.190600Z

It indeed reduced from 117MB -> 109MB 🙂

ericdallo 2021-02-13T16:12:55.190800Z

it's something indeed, with UPX this should be < 29MB

ericdallo 2021-02-13T16:13:05.191Z

thanks for the help @borkdude

borkdude 2021-02-13T16:13:13.191200Z

:)

ericdallo 2021-02-12T16:11:52.178Z

just tried adding to the :jvm-opts of my :native-image profile that is used during the uberjar:

:jvm-opts ["-Xmx2g"
   "-server"
   "-Dclojure.compiler.direct-linking=true"
   "-Dclojure.spec.skip-macros=true"
   "-Dborkdude.dynaload.aot=true"]

ericdallo 2021-02-12T16:12:02.178200Z

and to the graalvm compilation flag:

ericdallo 2021-02-12T16:12:16.178400Z

"-J-Dborkdude.dynaload.aot=true"

ericdallo 2021-02-12T16:13:10.179100Z

looks the same I'm using

ericdallo 2021-02-12T16:13:16.179300Z

the println prints nil

ericdallo 2021-02-12T16:14:21.179500Z

hum, if I java -jar it still prints nil

ericdallo 2021-02-12T16:14:40.179700Z

so the issue is the flag in the jar

borkdude 2021-02-12T16:15:40.179900Z

so direct linking also doesn't work? good to check because that is also important

ericdallo 2021-02-12T16:16:19.180100Z

yeah, I'll check it too, probably is not working 😨

borkdude 2021-02-12T16:16:58.180300Z

direct linking will likely make your image smaller as well

1🤞
ericdallo 2021-02-12T16:18:31.180700Z

so with lein with-profile native-image run it prints true

ericdallo 2021-02-12T16:18:43.180900Z

but with the generated jar not, let me debug

ericdallo 2021-02-12T16:41:35.181100Z

so I changed the uberjar task to this:

:uberjar {:aot :all
                       :jvm-opts ["-Dclojure.compiler.direct-linking=true"
                                  "-Dclojure.spec.skip-macros=true"
                                  "-Dborkdude.dynaload.aot=true"]}
But even when lein uberjar &amp;&amp; java -jar target/clojure-lsp-*-standalone.jar I still get the nil print for all those variables

ericdallo 2021-02-12T16:41:57.181300Z

I tested a lot of params, even moving the jvm-opts to the root of the project.clj

ericdallo 2021-02-12T16:42:05.181500Z

it only work for lein run

ericdallo 2021-02-12T16:42:30.181700Z

I checked babashka and the config is the same

ghadi 2021-02-12T21:47:01.182700Z

has anyone any experience making a native image with the Kafka client lib in it?

1👀
ericdallo 2021-02-12T21:54:11.183Z

This seems to compile a producer and consumer with clojure: https://github.com/dainiusjocas/clojure-kafka-graalvm-native-image Maybe can help you

borkdude 2021-02-12T22:52:35.183300Z

There is also this: https://github.com/tzzh/pod-tzzh-kafka A pod which you can use from babashka scripts.