Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GraalVM native-image support #47

Open
viesti opened this issue Jul 22, 2019 · 22 comments
Open

GraalVM native-image support #47

viesti opened this issue Jul 22, 2019 · 22 comments

Comments

@viesti
Copy link
Contributor

viesti commented Jul 22, 2019

This would allow building to native executable. I'm thinking that we could add a namespace for calling the native-image tool, with suitable defaults (example from jet).

@SevereOverfl0w
Copy link
Collaborator

If I did this I'd want it to be really easy, no setting of GRAAL_HOME or whatever. It should just be automatic.

@SevereOverfl0w
Copy link
Collaborator

https://www.graalvm.org/sdk/javadoc/ is this what we are after? The native image parts? Not sure.

@viesti
Copy link
Contributor Author

viesti commented Jul 22, 2019

I didn't actually go as far as checking if there is a Java API available. If such exists, it would be a good match to help with being "automatic" :)

@SevereOverfl0w
Copy link
Collaborator

@viesti
Copy link
Contributor Author

viesti commented Jul 22, 2019

Ahaa!, that set's a target for us then :)

@viesti
Copy link
Contributor Author

viesti commented Jul 22, 2019

I have to admit not doing proper background research as there are atleast two tools, https://github.com/luchiniatwork/cambada and https://github.com/taylorwood/clj.native-image, that operate in this area. If native-image has a library api (and is available as a dependency), it would set pack apart from the other tools.

@viesti
Copy link
Contributor Author

viesti commented Jul 22, 2019

This looks a bit bad 😬 https://github.com/oracle/graal/blob/master/substratevm/src/native-image-maven-plugin/src/main/java/com/oracle/substratevm/NativeImageMojo.java#L166:

Path nativeImageExecutable = getJavaHome().resolve("bin").resolve(withExeSuffix("native-image"));

The "Simplifying native-image generation with Maven plugin and embeddable configuration" post states:

If you are using GraalVM as your JAVA_HOME it is sufficient to just add:

<plugin>
   <groupId>com.oracle.substratevm</groupId>...

So I guess it relies on the native-image tool being available in the path.
Anyway, thanks for helping on looking into this :)

@SevereOverfl0w
Copy link
Collaborator

There's also this following that:

it is also possible to build images even without having a GraalVM release installed on your system. The only requirement is to have a JVMCI enabled JDK on your machine. 

@SevereOverfl0w
Copy link
Collaborator

Seems like JVMCI is a draft proposal, and only graal is building open jdk with it for now. (These are both statements that need confirming).

I would not be opposed to downloading graalvm into a cache directory and shelling out to that native-image if graalvm cannot be found via the normal methods.

@SevereOverfl0w
Copy link
Collaborator

jvmci doesn't exist in my oracle jdk install..

@viesti
Copy link
Contributor Author

viesti commented Jul 22, 2019

Seems that from 19.00 onwards (see github releases page), native-image was extracted from the Graal distribution and is available as a jar, but it is not independent and relies on the Graal distribution. 300MB of Graal seems like quite a drink in the cache, but might still be worth a try for better usability :) I wonder what is the minimum of deps that the utility actually needs from inside graal...

@SevereOverfl0w
Copy link
Collaborator

It's a big cache, but you will need it downloaded either way. Pack can do it for you, or you can do it and specify the location. The cache would be a fallback. Some kind of garbage collection seems worthwhile though.

The idea of tree shaking graal sounds interesting :p.

@viesti
Copy link
Contributor Author

viesti commented Jul 23, 2019

Thinking out loud:

Maybe we could check for latest release of Graal and even prompt to upgrade to it. A --cache-dir that has a default (say ~/graalvm-cache) would allow users to manage the location of the install. A Graal version could even be selectable via --version, which would default to latest version in the cache directory.

I don't know if native-imagehas different release schedule than graal itself. If so, this might be an additional update step. Initial (and updates) download of native-image could be done via gu utility, so we don't have to perform native-image installation.

@SevereOverfl0w
Copy link
Collaborator

My thinking was something along the lines of checking for GRAALVM_HOME, checking if JAVA_HOME contains native-image, then finally creating/updating the cache otherwise.

https://github.com/soc/directories-jvm I'd probably use this for the cache location, because I'm a sucker for compliance.

@viesti
Copy link
Contributor Author

viesti commented Jul 24, 2019

TIL directories-jvm :) This sounds like good reasoning to me.

@viesti
Copy link
Contributor Author

viesti commented Sep 28, 2019

Doodling thoughts here: It occurred to me that maybe a native-image based AWS Lambda custom runtime could be an spot open in the Clojure cloud tooling :) Pack already has a command for packaging a Lambda for the JVM runtime, but the custom runtime with native-image/SubtrateVM would have better startup time. We could also take care of things like bundling libsunec.so, which would be quite convenient for the user (maybe do deploy also).

@SevereOverfl0w
Copy link
Collaborator

SevereOverfl0w commented Dec 6, 2019

OpenJDK11 does support JVMCI behind a flag:

❯ clj -J-XX:+UnlockExperimentalVMOptions -J-XX:+EnableJVMCI
Clojure 1.10.1
user=> (import '[com.sun.management HotSpotDiagnosticMXBean VMOption])com.sun.management.VMOption
user=> (def bean (ManagementFactory/getPlatformMXBean HotSpotDiagnosticMXBean))
WARNING: bean already refers to: #'clojure.core/bean in namespace: user, being replaced by: #'user/bean
Syntax error compiling at (REPL:1:11).
No such namespace: ManagementFactory
user=> (import '[java.lang.management ManagementFactory])java.lang.management.ManagementFactory
user=> (def bean (ManagementFactory/getPlatformMXBean HotSpotDiagnosticMXBean))
#'user/bean
user=> (.getVMOption bean "EnableJVMCI")#object[com.sun.management.VMOption 0xbb9ab64 "VM option: EnableJVMCI value: true  origin: VM_CREATION (read-only)"]
user=> 

This might be good enough (with a fallback env var for JDK 8 for users who really need it)

@viesti
Copy link
Contributor Author

viesti commented Dec 7, 2019

Hmm, so in the subtratevm readme, it says

Native image generation is performed by a Java program that runs on JDK 8 with JVMCI.

So how does one get this program, is there a maven library? Seems that I haven't studied this enough :)

@SevereOverfl0w
Copy link
Collaborator

SevereOverfl0w commented Dec 7, 2019 via email

@SevereOverfl0w
Copy link
Collaborator

The JVMCI approach was later removed, unfortunately. oracle/graal@1ee1262

@SevereOverfl0w
Copy link
Collaborator

It appeared to work by using an artifact like https://mvnrepository.com/artifact/org.graalvm.nativeimage/svm-hosted-native-windows-amd64/22.1.0 and untarring it to a target directory... This might still be viable. The release seems recent still. We already have TDA on the classpath so fetching the correct tar.gz shouldn't be a problem.

@SevereOverfl0w
Copy link
Collaborator

One interesting idea might be to leverage the fact that most devs have docker installed, even if they don't have graalvm installed. It would also make it easier to have a reproducible version of native-image that's used per project.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants