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/.
chrisn 2021-03-20T12:48:11.021300Z

@huahaiy - that isn't the case. I have three 'ffi's implemented. libpython-clj, for example already works on with JNA direct mapping and JDK-16 and it just depends on what dtype-next's ffi system finds on the system. You write one https://github.com/clj-python/libpython-clj/blob/master/src/libpython_clj2/python/ffi.clj and it works across https://github.com/cnuernber/dtype-next/blob/master/src/tech/v3/datatype/ffi/jna.clj, https://github.com/cnuernber/dtype-next/blob/master/src/tech/v3/datatype/ffi/mmodel.clj, and https://github.com/cnuernber/dtype-next/blob/master/src/tech/v3/datatype/ffi/graalvm.clj. So you, as the implementor, do not have to write multiple FFI layers yourself. You write one, describe it with data, and I translate that data into the subsystem-appropriate classes and implementations.

borkdude 2021-03-20T12:57:55.022300Z

That's great, no more writing JNI stuff I guess

chrisn 2021-03-20T12:58:57.023800Z

I have a link just for you - https://graalvm.slack.com/archives/CN9KSFB40/p1616200527026800?thread_ts=1616189277.022900&cid=CN9KSFB40. I made a bit of noise on the graalvm native-image channel and got a fantastic response.

borkdude 2021-03-20T12:59:06.023900Z

@chris441 Does this also work if you want to expose Clojure stuff as a native lib? like I did here? https://github.com/borkdude/sci/blob/master/doc/libsci.md

chrisn 2021-03-20T13:00:07.025Z

I can try to expose avclj as a native lib and we can find out. My overall goal was to get some nontrivial portion of libpython-clj working both as an executable and as a native lib.

chrisn 2021-03-20T13:00:31.025400Z

So people could write python extensions in Clojure but be able to talk back to the python system that loaded them.

borkdude 2021-03-20T13:00:51.025700Z

My question is just out of curiosity, not that I have any plans

chrisn 2021-03-20T13:01:50.026300Z

As far as JNI is concerned, the best way to do that is javacpp.

chrisn 2021-03-20T13:01:57.026500Z

Nothing else is even close IMO.

chrisn 2021-03-20T13:02:14.027100Z

I used that for cortex and aside from some teething issues it worked great.

chrisn 2021-03-20T13:02:44.028100Z

But I don't like JNI. I like to find libraries dynamically so I can account for version changes in code without separate releases bound to specific binary versions of things.

borkdude 2021-03-20T13:02:58.028500Z

I guess I could ask the question like: avclj compiles to an executable. Is it possible to compile it a shared library again (which kind of defeats the purpose of that app, but just as an example), so you can call that shared lib from python as a native lib?

chrisn 2021-03-20T13:03:32.029Z

It should be. Nothing I did precludes that.

chrisn 2021-03-20T13:03:45.029300Z

Well, nothing that I know that I did precludes that.

borkdude 2021-03-20T13:04:05.029600Z

cool stuff.

chrisn 2021-03-20T13:04:16.029900Z

🙂. Appreciated. Agreed 🙂.

chrisn 2021-03-20T13:06:20.031200Z

I do have a question. Sometimes I have an extra require or something that really explodes both the build time and the executable size. It usually takes me quite a long time to track down the pprint statement or whatever that causes it. Are there any tricks to tracking down these issues faster?

chrisn 2021-03-20T13:06:54.032Z

For instance, RT/var will cause the explosion as will pprint.

borkdude 2021-03-20T13:07:53.033100Z

@chris441 I usually just do this by divide and conquer. Start as small as possible and then start adding things. Things known to explode: Look up vars at runtime. E.g. require, resolve, requiring-resolve. I have made a patch in babashka to avoid the explosion of pprint. Also I made this variation of dynaload that won't blow up the binary: https://github.com/borkdude/dynaload

borkdude 2021-03-20T13:08:26.033600Z

Also I have logged a JIRA issue about pprint

borkdude 2021-03-20T13:09:33.034200Z

https://clojure.atlassian.net/browse/CLJ-2582

chrisn 2021-03-20T13:09:33.034300Z

Beautiful, dynaload is a great insurance policy.

borkdude 2021-03-20T13:10:21.034700Z

Possibly you can use https://github.com/borkdude/grasp to find these likely causes

borkdude 2021-03-20T13:10:46.035400Z

Grasp for non-top-level require, find-var, requiring-resolve, resolve

chrisn 2021-03-20T13:11:41.036300Z

Yep, makes sense. Interestingly enough, RT/var in the static initialization code section of a class doesn't cause it. But RT/var in any instance-level code definitely well.

borkdude 2021-03-20T13:13:46.038300Z

I think GraalVM static analysis accounts for static initialization, which is influenced by --initialize-at-runtime and --initialize-at-build-time. Is (var x) triggering something? This is a special form which is compiled away to the var object I think?

borkdude 2021-03-20T13:14:36.039100Z

If GraalVM can't decide that an entire namespace isn't needed, it may leave all vars/functions around and everything related to it, which may blow up the binary, is my guess

borkdude 2021-03-20T13:14:46.039400Z

Sometimes -J-Dclojure.compiler.direct-linking=true also helps

borkdude 2021-03-20T13:18:21.040300Z

Maybe I should add a graalvm native-image linter to clj-kondo :thinking_face:

chrisn 2021-03-20T13:18:39.040700Z

well, and with multimethods and protocol implementations graal often can't figure out if a namespace is OK to elide and I can't blame them.

borkdude 2021-03-20T13:19:01.040900Z

true

chrisn 2021-03-20T14:07:35.041500Z

It looks like we can include the truffle nfi in a native image. That would give you a cython-equivalent system I believe.

Huahai 2021-03-20T19:03:09.042Z

nice