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-01-29T01:18:43.050800Z

Ok, use the direct-linking helped reducing some weird classes, I used the output config to the native image input and the result looks better than before 😄 now it seems to load LSP correctly and communication work (json ser/deser), but I'm having a issue when responding with clojure.spec.alpha/conform https://github.com/clojure-lsp/clojure-lsp/blob/master/src/clojure_lsp/interop.clj#L409. Basically we use this function everytime we want to respond to client, so we validate if server response is following the spec and do some clj-map->java transformations (nothing magical, just instantiating the class manually) https://pastebin.pl/view/6450ceea

ericdallo 2021-01-29T03:32:00.051500Z

It was related with some instances not being recognized in runtime, fixed it using some type hints 😄

lukasz 2021-01-29T14:58:24.053800Z

That's amazing, heaviness of clojure-lsp was a bit of a show stopper for me in the early days, can't wait to try out the native-image version

1😉
dharrigan 2021-01-29T15:12:40.054300Z

Yes, looking forward to this one indeed!

2021-01-29T16:21:20.055800Z

Looking forward to it! Maybe you can even write a report of your adventure so that we can maybe profit on the java->native experience!

1
ericdallo 2021-01-29T18:48:08.056500Z

Hey @borkdude Just got a corner case with sqlite 😕 It seems to throw a segfault when the db does not exists: (missing .lsp/sqlite.db) https://pastebin.com/JqHJPJzk

ericdallo 2021-01-29T18:48:32.056700Z

Right on this line: https://github.com/clojure-lsp/clojure-lsp/blob/master/src/clojure_lsp/db.clj#L35

borkdude 2021-01-29T18:49:33.057Z

@ericdallo I don't know what causes this. Where did you get the suggestions for the reflection / JNI config for sqlite?

ericdallo 2021-01-29T18:50:27.057200Z

Right here: https://github.com/xerial/sqlite-jdbc/issues/413

ericdallo 2021-01-29T18:50:42.057500Z

From the example: https://github.com/xerial/sqlite-jdbc/issues/413#issuecomment-525926912

borkdude 2021-01-29T18:52:09.058Z

@ericdallo Does his Java example work correctly when the db does not exist?

ericdallo 2021-01-29T18:52:27.058200Z

Hum... I didn't test, good point, I'll test it

borkdude 2021-01-29T18:53:56.058500Z

And to double check, you added all these classes to the JNI config right? https://github.com/mageddo/graalvm-examples/blob/59f1f1bf09894681edfddaa100b4504770ad0685/sqlite/src/main/java/com/mageddo/sqlite/JNIReflectionClasses.java#L46-L55 and to reflection

borkdude 2021-01-29T18:54:51.058900Z

Also try graalvm java 8 instead of 11

ericdallo 2021-01-29T19:01:57.059100Z

Yes, they are on https://github.com/ericdallo/sqlite-jni-graal-fix workaround

ericdallo 2021-01-29T19:02:18.059500Z

reflection not really

ericdallo 2021-01-29T19:03:22.059700Z

Oh, just found some classes missing from the fix, I don't know why, I'll add them too

ericdallo 2021-01-29T19:03:54.060300Z

Oh, yeah, so it's enough probably

ericdallo 2021-01-29T19:04:02.060500Z

I realized it's missing the Throwable class

ericdallo 2021-01-29T19:04:16.060700Z

since when don't find the db it should throw an exception, may be related

borkdude 2021-01-29T19:04:28.060900Z

yeah

1
borkdude 2021-01-29T19:14:15.061200Z

Btw, Quarkus is a Java framework by Oracle of which all extensions can be compiled to native. Sometimes nice to borrow stuff from as well: https://github.com/quarkusio/quarkus/tree/master/extensions/jdbc

ericdallo 2021-01-29T19:15:25.061400Z

Hum, interesting

ericdallo 2021-01-29T19:49:05.061600Z

Yep, it fixed the issue 🙂 Probably it was the missing Throwable... that is not on that repo master, only on that specific commit

borkdude 2021-01-29T19:49:21.061800Z

cool

ericdallo 2021-01-29T19:49:35.062Z

a segfault like that is really hard to debug...

borkdude 2021-01-29T19:49:42.062200Z

yep

borkdude 2021-01-29T19:50:32.062400Z

this is why you should probably not just switch to native, but offer this as something experimental ;)

borkdude 2021-01-29T19:50:40.062600Z

and keep offering the JVM jar as well

borkdude 2021-01-29T19:50:57.062800Z

among other reasons

borkdude 2021-01-29T19:51:28.063Z

but it's cool that you got sqlite to work. maybe I can switch my pod from go to clojure now ;) although the golang pod is really small (few megabytes)

borkdude 2021-01-29T19:52:11.063200Z

does LSP native not require you to have sqlite installed, some libsqlite thing on your system? maybe try the binary in a bare ubuntu docker image (if that hasn't got it by default)?

ericdallo 2021-01-29T19:58:19.063500Z

Yeah, My idea is if everything work provides that as experimental for some time

borkdude 2021-01-29T19:59:12.063700Z

Note that if you exclusively offer the native, you will probably have to provide it for the three major OSes and also a static one for alpine

ericdallo 2021-01-29T19:59:24.063900Z

yes, since I use NixOS there is no way to use a lib that I didn't tell it to use, but a test on a docker it'd really help to make sure

ericdallo 2021-01-29T20:00:05.064100Z

Yes, I have in mind setup a CI for the 3 OS building via GH actions, just like babashka

1
ericdallo 2021-01-29T20:19:29.064400Z

@borkdude how the nrepl just for dev would work? In the code should I check somehow what is the profile/some env var? This would affect graal?

ericdallo 2021-01-29T20:20:23.064600Z

I can add the dep for the dev profile only, but my question is how should I code that to use for dev only or something like that

borkdude 2021-01-29T20:22:07.064800Z

yeah, you can do it through an env var or just by trying to resolve it on the top level:

(when-let [server-var (try (requiring-resolve 'nrepl.server/server) (catch Exception e nil))]
  ...

borkdude 2021-01-29T20:22:29.065Z

note that it's best to keep this at the top level so it's not resolved at run time

borkdude 2021-01-29T20:22:39.065200Z

the native-image will compile this away

borkdude 2021-01-29T20:23:20.065400Z

and then of course you move the nrepl deps to a dev profile

borkdude 2021-01-29T20:23:23.065600Z

or alias

ericdallo 2021-01-29T20:23:46.065800Z

got it, do you use anything like that in your projects?

borkdude 2021-01-29T20:41:07.066Z

yeah, this is how all the features in babashka are implemented

borkdude 2021-01-29T20:41:17.066200Z

see build.md, feature flags

ericdallo 2021-01-29T20:43:00.066400Z

cool, thanks!

borkdude 2021-01-29T20:44:30.066600Z

@ericdallo I also have this library: https://github.com/borkdude/dynaload

ericdallo 2021-01-29T20:47:54.067300Z

that dynaload seems to fit perfect this use case

ericdallo 2021-01-29T20:49:00.067500Z

should I wrap the dynaload call with a try catch to check if nrepl is enabled? Or is better to check a env var?

borkdude 2021-01-29T20:49:57.067700Z

What you can do is do a require based on an env var. And then use dynaload to use the var(s)

ericdallo 2021-01-29T20:50:23.067900Z

what is the point to use dynaload if I can just require 'mylist ? I think I don't get it

ericdallo 2021-01-29T20:50:58.068100Z

Oh, it won't compile if I don't require it.. it makes sense

ericdallo 2021-01-29T20:51:08.068300Z

dynaload just use a symbol and do the magic

borkdude 2021-01-29T20:51:10.068500Z

this is more useful for libraries than apps probably. in libraries you can say: I can work with these vars, if you have required the lib already

borkdude 2021-01-29T20:51:33.068700Z

in normal JVM dynaload will also do the require for you

borkdude 2021-01-29T20:51:40.068900Z

but for GraalVM this has a negative impact on binary size

borkdude 2021-01-29T20:51:52.069100Z

although it will still work

ericdallo 2021-01-29T20:52:35.069300Z

I see

borkdude 2021-01-29T20:53:07.069500Z

To keep it simple: Just do a try catch where you try to require/resolve the lib/vars. If you then provide the library on your classpath, the vars will work. Else they won't do anything.

ericdallo 2021-01-29T20:53:47.069700Z

great