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/.
2021-03-11T11:33:00.141600Z

I'm trying to do the hello-world tutorial on clj-graal-docs on windows and hitting issues. I have my folder structure and the main.clj and deps.edn. It compiles when I do

clojure -M -e "(compile 'hello-world.main)"
Then it says verify it works on the JVM with
$ java -cp $(clojure -Spath):classes hello_world.main
Hello world!
When I run that java command I get an error.
Error: Could not find or load main class :classes
Caused by: java.lang.ClassNotFoundException: :classes
The output to the classes folder it asked me to create was this: I'm not familiar enough with the CLI tools to know if that command to compile is wrong, or I'm doing something else stupid.

borkdude 2021-03-11T11:34:21.142400Z

@qmstuart $(clojure -Spath) is bash syntax

2021-03-11T11:34:31.142600Z

ah ok, doh!

borkdude 2021-03-11T11:34:58.143200Z

I do have some windows examples

borkdude 2021-03-11T11:35:01.143400Z

let me check

borkdude 2021-03-11T11:36:16.145300Z

@qmstuart For Windows (and in general now) I tend to first build an uberjar and then feed that uberjar to graalvm. This also takes care of "too long" classpath issues on Windows

2021-03-11T11:37:06.146400Z

thank you!

borkdude 2021-03-11T11:37:15.146600Z

^ @lee this is what I was getting at with the Windows classpath / uberjar problem, it's one of the two issues

wombawomba 2021-03-11T11:38:20.147500Z

So I'm compiling a command-line app using native-image, and the resulting binary weighs in at a whopping 94 MB. I ran native-image with -H:DashboardDump=dashboard -H:+DashboardCode to try to tell where all this weight is coming from (`-H:+DashboardAll` crashes with a message about deadlock), but looking at the result at https://www.graalvm.org/docs/tools/dashboard the total size adds up to only 37 MB. Any idea what's going on here?

borkdude 2021-03-11T11:40:45.148500Z

@wombawomba There are a few things which can bloat the binary size in clojure projects. I have seen this happen mostly with runtime requires/requiring-resolve usages

borkdude 2021-03-11T11:41:57.149Z

Usually I find out about this by starting small and then adding more stuff, to find out what triggers it

wombawomba 2021-03-11T11:45:25.150600Z

@borkdude any ideas on how to start if I want to try something like that? Currently my build command is native-image --allow-incomplete-classpath --enable-http --enable-https --initialize-at-build-time --initialize-at-run-time=org.jline.terminal.impl.jansi.win.JansiWinSysTerminal,org.jline.terminal.impl.jna.win.JnaWinSysTerminal --no-fallback --no-server --report-unsupported-elements-at-runtime --verbose (the --inititalize-at-run-time arg seem to be required for https://github.com/jline/jline3)

borkdude 2021-03-11T11:46:13.151300Z

The first start is just print hello world from your main.

borkdude 2021-03-11T11:46:22.151600Z

And then add one function to it at a time

2021-03-11T11:47:18.152400Z

@borkdude your video on graalvm native hello world is good and helpful. Thanks for making these little videos šŸ™‚

šŸ™ 1
wombawomba 2021-03-11T11:47:47.152700Z

alright

lread 2021-03-11T11:56:09.153700Z

thanks, I think I can work this into a tip

borkdude 2021-03-11T11:57:49.153900Z

or we can add a Windows-friendly hello world in there

lread 2021-03-11T11:58:25.154200Z

that too

2021-03-11T12:34:55.156500Z

Error: Native-image building on Windows currently only supports target architecture: AMD64 (x86 unsupported)
Error: To prevent native-toolchain checking provide command-line option -H:-CheckToolchain
com.oracle.svm.core.util.UserError$UserException: Native-image building on Windows currently only supports target architecture: AMD64 (x86 unsupported)
Where can I specify x86 v x64 ?

2021-03-11T12:36:48.156800Z

or maybe this a consequence of teh VS I have installed, and therefore the cl.exe ?

2021-03-11T12:43:36.157200Z

OK, you need to use the x64 developer command prompt to run graal-vm

2021-03-11T12:43:50.157400Z

ls

2021-03-11T12:44:23.157800Z

it works, i have a native windows.exe šŸ˜„

2021-03-11T12:56:48.158100Z

thanks for all the help šŸ‘

borkdude 2021-03-11T12:59:40.158300Z

yay!

2021-03-11T15:57:40.160200Z

What kind of file sizes do you folks see for binaries created with native-image? I always end up with sizes between 75-90mb (for clj+jetty+postgres+jdbc).

lukasz 2021-03-11T15:58:27.160400Z

Not bad!

2021-03-11T16:00:01.161100Z

This 75-90mb is from uberjars around 10mb šŸ™‚

borkdude 2021-03-11T16:09:16.162100Z

@thegeez Hello world is around 10mb. With sci (interpreter) not much more. Adding postgres to babashka adds around 3mb, not much. But I think the incremental size depends on what you were already using before.

borkdude 2021-03-11T16:09:33.162500Z

Babashka itself is now 70mb on macos. I curate every lib that goes in to make sure the binary size doesn't blow up

borkdude 2021-03-11T16:10:15.163500Z

There are a few things that can trigger binary size to blow up, such as runtime requires/resolve

2021-03-11T16:11:01.164100Z

Thanks, then it might be worth it to investigate getting lower sizes for my case. Thus far I always assumed 60mb as the lowest bar

borkdude 2021-03-11T16:12:02.164700Z

E.g. clojure.pprint has some usage of find-var inside of it. I patched that to make the vars known at at compile time. This took care of a couple of dozen mbs.

borkdude 2021-03-11T16:12:53.165400Z

There is also https://github.com/borkdude/dynaload which gives better binary size than the clojure.spec dynaload

borkdude 2021-03-11T16:14:48.166100Z

@thegeez babashka has httpkit built in. this only added 1.5mb to the binary including the http client

borkdude 2021-03-11T16:15:06.166500Z

But adding the full ring stack will probably bloat stuff again due to some require at runtime somewhere

borkdude 2021-03-11T16:15:24.166900Z

This has already been patched by someone who wanted to add ring to bb

2021-03-11T16:20:22.168200Z

Alright I guess I'll need to do a day of trail-and-error compilation to try to get down to those numbers. Too bad each native-image compilation takes around 6 mins on my machine

borkdude 2021-03-11T16:25:06.168500Z

Yes, this can be a painful process...

lukasz 2021-03-11T16:47:44.170300Z

I'm genuinely curios about the concern around binaries size - if it's was 0.5GB I'd be worried, but 90MB feels like nothing nowadays. It kinda makes sense for bb in some way, then again node_modules in one of our apps is 650MB....

2021-03-11T16:53:12.172Z

It is not a problem for my use-case, which is aws lambda, the zip size is 20mb. But if there's any further improvement possible I'll gladly take it. Because deploy is compilation (~6min) -> upload 20mb

borkdude 2021-03-11T16:56:26.174400Z

@thegeez Yeah, maybe not worry about this. 90mb sounds fine for an "app". clojure-lsp is also this size. Thinking about it though: both projects use next.jdbc. After upgrading recently I saw the binary size of babashka pods grow to 50mb, so it may be explained from this lib usage as well. Anyway, I agree with @lukaszkorecki: if this is something you use in private, then it's no big deal, if it's used by the masses, maybe more, but maybe still not a big deal.

2021-03-11T17:00:36.175500Z

I'm already happy that I don't need to change to use for instance ClojureScript on nodejs to use lambda, so far native-image is great already.

2021-03-11T17:01:22.176400Z

But it would also be awesome if I could email around the final binaries šŸ™‚

borkdude 2021-03-11T17:01:55.177Z

If you're using amazon, put it in a zipfile on s3? ;)

lukasz 2021-03-11T17:02:25.177600Z

Ah, I was not aware of the lambda file limit - we deploy Clojure on JVM in lambda and the uberjar size is <10MB so we're well below that. That said, the newly released Lambda + container images effectively eradicates that issue.

2021-03-11T17:03:43.178300Z

It's zipfile on s3 right now, that won't change even with a smaller size

borkdude 2021-03-11T17:03:52.178600Z

I don't think thegeez said that aws lambda has a binary size limit?

2021-03-11T17:05:01.179200Z

It's nice to have, rather than must have. Which is good enough already

borkdude 2021-03-11T17:05:56.179700Z

@thegeez What is the use case of a webapp on aws lambda? afaik you don't need a webserver to process lambda invocations right?

2021-03-11T17:09:53.181Z

It's API Gateway -> Lambda bootstrap custom runtime. The runtime handles http calls containing lambda events from the API Gateway which gets http calls from browsers

2021-03-11T17:11:16.181900Z

I think all lambda request handler libraries/frameworks expose a web handler to receive requests, but perhaps there are other ways

ghadi 2021-03-11T17:13:24.183900Z

Iā€™m working on a custom Lambda runtime at Cognitect, interested in your use cases

lukasz 2021-03-11T17:14:52.184900Z

I prototyped bb+Lambda+container image, doesn't get easier than this: https://gist.github.com/lukaszkorecki/a1fe27bf08f9b98e9def9da4bcb3264e

lukasz 2021-03-11T17:15:00.185200Z

no need for custom runtimes etc

2021-03-11T17:16:16.186200Z

My use case is web-app with cljs front-end for real-time collab over API Gateway websockets, web app is API Gateway HTTP api to lambda talking to Postgres rds database. This is a prototype atm

borkdude 2021-03-11T17:17:12.186800Z

So the webserver is short-lived, as soon as the person disconnects, the lambda can go to sleep again, let's say?

2021-03-11T17:20:35.189Z

A single lambda can handle consecutive reqs, but may disappear at any time (in my setup; there's no full webserver handling concurrent requests)

borkdude 2021-03-11T17:21:20.189700Z

right, so if there are no requests for a long time, you don't pay amazon. that's nice for low traffic websites/apps

2021-03-11T17:22:08.190600Z

I saw a tweet that describes serverless as "pay per request" architecture, that fits I think

borkdude 2021-03-11T17:22:17.190900Z

and also for very high traffic, since it scales automatically =)

2021-03-11T17:23:42.192Z

My goal is more lowest devops/most convenient devops required. I don't do well managing hardware

borkdude 2021-03-11T17:27:06.192300Z

You're still managing hardware though ;)

borkdude 2021-03-11T17:27:16.192500Z

Thanks for sharing your setup.

2021-03-11T17:27:35.192900Z

Yes serverless is a lie šŸ™‚

2021-03-11T17:27:46.193300Z

Thanks for sharing your numbers

borkdude 2021-03-11T17:28:07.193700Z

FYI, we moved to AWS now at Doctor Evidence, no more manual hardware fixes ;)

2021-03-11T17:28:58.193900Z

Nice!

2021-03-11T18:51:11.194100Z

Correction to what I said above, there's no webserver in the native-image. It's browser -req-> API Gateway <-req- native app. So the native app on lambda only needs an http client.

borkdude 2021-03-11T18:57:13.194900Z

Then the image could be fairly small (depending on what else it does). Which client are you using? Clj-http is known to bloat the binary. Http-kit is much better there

borkdude 2021-03-11T18:57:37.195200Z

Does the image still do the db stuff?

2021-03-11T18:59:51.195800Z

http through clj-http-lite, the jdbc.next+postgres is still there

ghadi 2021-03-11T18:59:57.196Z

http://java.net.http FTW

borkdude 2021-03-11T19:01:14.196500Z

yes, but don't use a wrapper like hato, it has even worse bloat due to all sorts of runtime requires

borkdude 2021-03-11T19:02:37.197Z

Perhaps https://github.com/exoscale/telex fairs better, since it's really minimal

lukasz 2021-03-11T19:03:25.198300Z

Underneath your lambda never runs a web server - it GETs event data via a private metadata endpoint and POSTs results to it. So in Lambda runtime/SDK there usually is some http client included.

dangercoder 2021-03-11T21:12:03.198800Z

has anyone tried to compile a project depending on https://github.com/igrishaev/etaoin to a native-executable?

dangercoder 2021-03-11T21:23:18.199200Z

clj-http giving me some issues

borkdude 2021-03-11T21:28:09.199600Z

@jarvinenemil yes: https://github.com/babashka/pod-babashka-etaoin using that you can use etaoin from babashka

borkdude 2021-03-11T21:29:12.200200Z

This is a better example of the usage: https://github.com/babashka/pod-registry/blob/master/examples/etaoin.clj I should really update the README

borkdude 2021-03-11T21:30:58.201Z

@jarvinenemil I'm looking back now. I made a fork of etaoin: https://github.com/borkdude/etaoin-graal and published it to clojars: borkdude/etaoin-graal "0.3.7-alpha.1"

šŸ˜ 1
dangercoder 2021-03-11T21:35:02.203300Z

@borkdude I tried https://github.com/babashka/pod-babashka-etaoin but I will have to make pull-request filling in a few functions that I need (such as etaoin.api/get-element-attr . Working on it

borkdude 2021-03-11T21:36:00.204Z

@jarvinenemil I think we'll have to update it with etaoin proper as well

borkdude 2021-03-11T21:36:12.204200Z

it's 100 commits or so behind I see

dangercoder 2021-03-11T21:37:12.205100Z

ah

borkdude 2021-03-11T21:37:16.205300Z

I mean etaoin-graal. I will update it now

dangercoder 2021-03-11T21:37:25.205500Z

I figured, cool, thanks!

dangercoder 2021-03-11T21:40:53.206400Z

Really awesome that you had forked etaoin and made a graal-vm compatible version. I was just about to do the same

borkdude 2021-03-11T22:08:38.206700Z

@jarvinenemil Published upgraded version as: borkdude/etaoin-graal 0.4.2-deb92aaa21c59c52521f42c0177bbce9ac10a0e2

borkdude 2021-03-11T22:09:26.207Z

https://clojars.org/borkdude/etaoin-graal

borkdude 2021-03-11T22:09:52.207600Z

Now I'll update the version at pod-babashka-etaoin and I'll await your PR

šŸ‘ 1
dangercoder 2021-03-11T22:22:00.208400Z

Heads up if anyone is using --enable-all-security-services ,

The --enable-all-security-services option is now deprecated and it will be removed in a future release.
https://www.graalvm.org/reference-manual/native-image/JCASecurityServices/

borkdude 2021-03-11T22:28:45.209Z

It will be deprecated in favor of automatically detecting by static analysis