DEV Community

loading...

GraalVM native, not quite there yet

viniciusccarvalho profile image Vinicius Carvalho ・3 min read

Introduction

I wrote a couple of posts around GraalVM here at dev.to: Building a native CLI with Kotlin and GraalVM and Building a native ktor application with GraalVM

There's a lot of articles out there praising GraalVM for how fast applications start, and how little memory footprint it uses, and it's all true. However you don't usually see people talking about the tradeoffs.

I recently started a micronaut application to connect to mysql and present data over a rest controller. A simple, yet a bit more than hello world type of app. I'll follow up with a full post and source code soon.

So if you just look in the speed improvements alone it's quite exciting:

Here's my app running as a jar

20:42:29.364 [main] INFO  io.micronaut.runtime.Micronaut - Startup completed in 2085ms. 
Server Running: http://localhost:8080

And here it's running as a native image:

20:41:09.832 [main] INFO  io.micronaut.runtime.Micronaut - Startup completed in 37ms. 
Server Running: http://localhost:8080

However building the app is nothing short of painful. There are a lot of gotchas when it comes to native apps. Tooling is improving for sure, but you still need to be very careful around reflection (in this matter, micronaut is such a bless compared to Spring for example).

Just look at how much memory this simple app needs to be compiled on my laptop (2017 MacBook Pro 16GB RAM):

[micronaut-graal:1288]    classlist:   9,486.18 ms,  1.47 GB
[micronaut-graal:1288]        (cap):   3,953.01 ms,  1.47 GB
[micronaut-graal:1288]        setup:   5,767.97 ms,  1.47 GB
[micronaut-graal:1288]   (typeflow): 161,511.61 ms, 12.77 GB
[micronaut-graal:1288]    (objects): 164,768.04 ms, 12.77 GB
[micronaut-graal:1288]   (features):   9,852.69 ms, 12.77 GB
[micronaut-graal:1288]     analysis: 352,973.84 ms, 12.77 GB
[micronaut-graal:1288]     (clinit):   7,207.49 ms, 12.78 GB
[micronaut-graal:1288]     universe:  24,093.15 ms, 12.78 GB
[micronaut-graal:1288]      (parse):  19,852.03 ms, 12.79 GB
[micronaut-graal:1288]     (inline):  23,210.25 ms, 12.79 GB
[micronaut-graal:1288]    (compile):  56,323.43 ms, 12.80 GB
[micronaut-graal:1288]      compile: 111,321.81 ms, 12.80 GB
[micronaut-graal:1288]        image:  12,677.21 ms, 12.80 GB
[micronaut-graal:1288]        write:   4,104.11 ms, 12.80 GB
[micronaut-graal:1288]      [total]: 521,240.14 ms, 12.80 GB

My goal with this app was to run it as a serverless app on Google Cloud Run. So I had to build a docker container and push it to gcr.io. And since I needed to build a linux image, not a OSX, I used Google Cloud Build, problem is that Cloud Build crashes with this, the regular instance can't handle 13GB of memory requested by a container, so I had to beef it up: gcloud builds submit --machine-type=n1-highcpu-32

Final thoughts

Before even writing about the application or how much speed I was able to squeeze out of a java app, I think its important to look on how much time you as developer will spend chasing reflection issues, or waiting for the compilation stages to finish.

GraalVM has a promising future, and I'm hopeful for that, just maybe not ready for prime time yet.

Happy coding

Discussion (0)

pic
Editor guide