Akka and Graal’s native image tool

(Christopher Hunt) #1

I’d like to formulate a plan for having Akka offer out of the box support for Graal’s native-image tool. I fear that Akka will be left behind as other toolkits and frameworks gain such support.

Native image generation is not only important for fast startup, but also for reduced memory consumption. My tests of Graal’s native image tooling have shown a simple hello world app reduces its resident memory size by a factor of 10. Reducing resident memory has a positive impact on a business given reduced operating costs i.e. there are less machines required to run a system.

Outside of the JVM, using Graal’s native image tool can present Akka based services that compete with Go on all fronts. Go is fast becoming an alternative to using the JVM for microservices, particularly because of its focus on resource usage.

My initial experiments with Graal and Akka resulted in finding a Graal issue in rc1 (1). The Graal team haven’t been focused on Akka and I think that it is up to us, the Akka community, to bring Akka to their attention.

I’ve previously attempted to raise the subject of reduced resident memory usage for Akka, and got a lukewarm response (2). My former colleagues at Lightbend may recall me harping on the importance of addressing JVM resident memory usage over the years. My Landlord project was even formed to tackle this problem head on (3). Now that Graal is real, I’d like to test the water again and gauge whether any efforts in formulating a plan to tackle Akka and Graal’s native image support would be warmly received.

Thanks for reading this far. In summary, is there an interest in a pursuit of Akka for Graal’s native image tool?

(1) https://github.com/oracle/graal/issues/401#event-1611391317
(2) https://groups.google.com/forum/m/#!topic/akka-user/4Cq7urAKBAg
(3) https://github.com/huntc/landlord

(Konrad `ktoso` Malawski) #2

There is interest, open tickets for github issues you encounter. PRs welcome of course as well.

(Martynas Mickevičius) #3

I have been playing around with GraalVM native image generator and Akka applications on my free time as well. I got stuck when it came to running the generated image as the classloader is not available then.

(Christopher Hunt) #4

Thanks, Martynas. So what limitations are we hitting here specifically given https://github.com/oracle/graal/blob/master/substratevm/LIMITATIONS.md?

It sounds like Dynamic Class Loading - if so, then would this mean that Akka may never be suitable for native-image making given its use of classloading?

(Konrad `ktoso` Malawski) #5

As said a few times already; there is nothing core in Akka that “really relies on and needs” dynamic classloading. The mailboxes etc are nowadays found like this but it’s not a core thing and could be made to not use reflection. Please open specific tickets about things you find.

(Christopher Hunt) #6

Konrad, please note that I was responding directly to something that Martynas stated. I’m attempting to have a discussion.

(Konrad `ktoso` Malawski) #7

Sure, and I’m requesting a ticket to be opened about this. If it’s just the mailboxes a simple switch or flag could solve it - by far no “may never be suitable” as to phrased it, which could cause people to have a wrong impression.

(Patrik Nordwall) #8

All such classloading is done via DynamicAccess and the default implementation ReflectiveDynamicAccess. It is currently not possible to replace the implementation of DynamicAccess but we could easily support that via ActorSystemSetup parameters so that an application/library could provide it’s own custom DynamicAccess implementation that is creating requested instances or classes explicitly instead.

(Martynas Mickevičius) #9

The issue I bumped into (note that I did a very basic smoke-test) was that classloader was not available. Both classOf[MyClass].getClassLoader and Thread.currentThread.getContextClassLoader returned null. And therefore loading the config in the Typesafe Config library failed.

Since that is not listed in the SubstrateVM limitations, maybe that is a bug in SubtrateVM itself.

(Christopher Hunt) #10

Hey Martynas - a different bug to this one do you think? https://github.com/oracle/graal/issues/401

(Codrut Stancu) #11

GraalVM developer here. As mentioned in the limitations document, dynamically loading classes cannot be supported on SubstrateVM. However, that doesn’t mean that we cannot have ClassLoader objects in the image, especially since the ClassLoader is also used to load resources. This is being currently worked on and classOf[MyClass].getClassLoader and Thread.currentThread.getContextClassLoader should work in the near future. Of course for classOf[MyClass].getClassLoader to work the class needs to be visible during native image building and properly registered for reflection. We are also working on automatically detecting patterns like Class.forName("x.y.z.MyClass") and register referenced classes for reflection as long as the class name is a constant or it can be constant folded.

(Schmitt Christian) #12

Actually the problem of running akka on GraalVM is actually the reference.conf and application.conf files (Lightbend Config. These can’t be embedded in the native-image. (only Resource Bundles are supported, but sadly both are not resource bundles. (in some way
Even when they could be embedded, it would not work, because lightbend config uses a ClassLoader to load these resource files. (And I guess akka actually calls ConfigFactory.defaultReference which means that it always tries to load the reference.conf from the ClassPath)

(Oleg Ilyenko) #13

@schmitch I don’t think that this is true. The native-image option is called -H:IncludeResources (was quite hard to find it). It allows to include any resource files from the classpath (based on the regexp) in the native image. Recently I used it in a small project.

It works with http4s StaticFile.fromResource which uses Class.getResource under the hood. So it is able to load the resource file when running as a native image.

(Schmitt Christian) #14

Oh thanks, nice find. So this works with all files and not just ResourceBundles as noted here: https://github.com/oracle/graal/blob/master/substratevm/RESOURCES.md
Would be great if they would document that.

Edit: sadly Play/Akka uses ClassLoader.getResource (Typesafe Config) which does not work. (Class.getResource works…).
However while working again on Play and Graal if could get it to create an image that fails on runtime with:

Caused by: Configuration error: Configuration error[Context class loader is not set for the current thread; if Thread.currentThread().getContextClassLoader() returns null, you must pass a ClassLoader explicitly to ConfigFactory.defaultApplication]

Work is here:
Play branch https://github.com/schmitch/playframework/tree/substrate-vm-optimization
Play project https://github.com/schmitch/play-scala-starter-example/tree/substratevm

(Codrut Stancu) #15

GraalVM native-image now has ClassLoader support. You can read more details in this GiHub comment. We also documented -H:IncludeResources.

(Christopher Hunt) #16

Thanks for the update. I’m excited to take a look!