taylorwood / clj.native-image

Build GraalVM native images with Clojure Deps and CLI tools
MIT License
271 stars 20 forks source link

Question about jvm-opts #5

Closed aiba closed 5 years ago

aiba commented 5 years ago

In the README, it suggests setting up deps.edn as:

{:aliases {:native-image {...}}
 :jvm-opts ["-Dclojure.compiler.direct-linking=true"]}

But this will enable direct-linking in all contexts, even during development (where it may not be desired).

What about limiting direct-linking to the native-image alias, e.g.:

{:aliases {:native-image {...
                          :jvm-opts ["-Dclojure.compiler.direct-linking=true"]}}}

Would that work equally well?

taylorwood commented 5 years ago

Thanks for filing this issue, the README needs updating. I think a better way to pass this flag is in :main-opts under :native-image, so it's passed directly to GraalVM native-image:

{:aliases {:native-image
           {:main-opts ["-m clj.native-image core"
                        "-H:Name=my_app"
                        "-Dclojure.compiler.direct-linking=true"]}}}
borkdude commented 5 years ago

@taylorwood I'm not sure if this should maybe be:

-J-Dclojure.compiler.direct-linking=true

EDIT: I doubt if it should be passed to GraalVM at all. I think it's only relevant when you compile the Clojure code to .class files? So in that case it should go into the :jvm-opts of the alias. Note that top level :jvm-opts don't do anything, they're just ignored.

taylorwood commented 5 years ago

@borkdude thanks, I think you’re right. I’ll verify and update docs.

borkdude commented 5 years ago

@taylorwood A few more things:

I tried :jvm-opts ["-Dclojure.compiler.direct-linking=true"] in the native image alias. This resulted in GraalVM errors: it wasn't able to find certain functions in other namespaces. I found out this is because clj.native-image only compiles the main namespace, but not others. So I made a workaround by compiling all my namespaces with lein uberjar and then feeding those classes to clj.native-image (removing the code that cleans the compilation directory). Eventually that worked (but I didn't notice a huge difference in performance).

taylorwood commented 5 years ago

@borkdude thanks for the debugging notes! Docs updated.

I found out this is because clj.native-image only compiles the main namespace, but not others.

I've only been testing with very trivial projects so far. I've made a v0.0.6 release to discover/compile all namespaces in the deps.edn paths. I reproduced the issue and tested a fix with a slightly less trivial HTTP server project (w/two namespaces): https://github.com/taylorwood/lein-native-image/tree/master/examples/http-api

Please share the repo you're testing with if possible.

but I didn't notice a huge difference in performance

I haven't done any benchmarking but I've noticed the resulting native image size differs slightly.

borkdude commented 5 years ago

@taylorwood the project is clj-kondo. Confirming it works with the newer version. Thanks a lot!