Hacker News new | ask | show | jobs
by djhworld 3189 days ago
I think it's going to take me a while to learn about the module system in Java 9, I'm probably going to bank on watching other projects do it first to see if any best practises emerge as developers get used to the new way of working.

One thing I will say though is Java 9 has had a definite improvement on Java applications that run on my Raspberry Pi 3, I think because this got included http://openjdk.java.net/jeps/297

One application used to take 55s to start up, now it takes around 15s!

4 comments

> 15s

Still sounds ridiculous. Assuming this is how much time it takes to initialize the VM, I wonder if it would be possible to have a pool of VM processes that are already running and ready to accept an application code.

It's a spring boot application so comes with the baggage of initialising Spring + Spring MVC, that took a long time on JRE 8
I don't know if it's still a problem with Spring, but at a previous job about 8 years ago I was able to cut our application's start time from about 80 seconds to ~12 by writing a custom implementation of the logic that Spring used to find bridge methods to determine the proper annotations. We profiled the startup and found that over 80% of the time was being spent in reflection to resolve those bridge methods and that could be done significantly faster by using asm to load the classfile bytes and resolve the bridge method by looking directly at the invokevirtual call. Spring avoided this approach because it could fail in situations where the SecurityManager prevented filesystem access.

I don't know if that's still the case, but it always bugged me that Spring would slow down the >99% case by so much just to accommodate the <1% case.

Dave Syer looked at this topic recently[0]. Most of the time spent in loading isn't due to reflection or annotation processing: it's proportional to the number of classes loaded.

That said, Spring is fairly enthusiastic about pulling stuff. As he says:

> Since more beans mean more features, you are paying at startup for actual functionality, so in some ways it should be an acceptable cost. On the other hand, there might be features that you end up never using, or don’t use until later and you would be willing to defer the cost. Spring doesn’t allow you to do that easily. It has some features that might defer the cost of creating beans, but that might not even help if the bean definitions still have to be created and most of the cost is actually to do with loading and parsing classes.

I imagine that they'll keep poking at it, especially since they're working on Spring Cloud Function[1], where cold starts for single invocations are common.

[0] https://github.com/dsyer/spring-boot-startup-bench/tree/mast...

[1] http://cloud.spring.io/spring-cloud-function/

> most of the cost is actually to do with loading and parsing classes

It boggles my mind that loading and parsing even a few thousand classes is something that a human can perceive as "dog slow" when carried out by a quad-core 1.2 GHz CPU.

My understanding is that it's I/O bound, that the JVM more or less fetches each class from the JAR file or disk individually.

I am not sure if that's an implementation decision or whether it's imposed by the JVM specification. At some point I want to tinker with OpenJ9 to find out.

From my own experience, the class scanning for finding all annotations is usually the bottleneck.

I believe that the last version of Spring (5) has a way to do the scanning at compile time now.

> I wonder if it would be possible to have a pool of VM processes that are already running and ready to accept an application code

This was tried with Drip and the earlier Nailgun. The idea doesn't work as well as you'd think for several practical reasons (the JVM is very lazy, so a JVM that does nothing until it has user code to run does just that - nothing).

>Assuming this is how much time it takes to initialize the VM

Why would you assume that?

Bad assumption.
For ARM, always use Oracle VM. It's around 15x faster for my application.
Please read on http://openjdk.java.net/jeps/297: "The contribution from Oracle provides full C1 and C2 support for ARM, putting it on par with other architectures."

So from now on the OpenJDK will be as fast as Oracle VM on ARM!

You could probably cut that down even more by "building" your pen jvm with a restricted set of modules.
The improvement is good, of course, but isn't the whole thing a bit of a straw man? The previous version taking 55 seconds on a Pi 3 seems utterly unacceptable to me, it's actually a pretty capable processor, and even a 15 second startup is pretty slow. Why put up with that when there are modern options (Go and Rust spring to mind) which would do so much better?
Because not everyone cares about the startup time of an application on a platform that is 10 times slower than an intel CPU from 2012 when the application runs for more than a minute?

Also why are you even considering go as modern? The best compiled alternative to java is D and it's possible to disable the stop the world pause for specific threads by detaching them from the runtime which make it useful for realtime workloads while still being able to take advantage of the GC to boost your productivity when determinism is not important.

I don't think that's what 'straw man' means.
It's a website that's for personal use (a dashboard), I don't update it that often.