65 comments

[ 3.0 ms ] story [ 86.4 ms ] thread
Generally speaking, startup times for Java / JVM based apps should be worked on next by the teams behind it; in the container age, fast startup is a good thing. I know the JVM itself starts up fast enough, but then going with e.g. Spring on top of that just adds a minute of startup time - and I've no clue what it's doing, I wouldn't think loading config, registering services and opening up a servlet thingy would take so long.
I think the startup time in Spring got that long due to resolving graph of dependencies at runtime.
I remember reading somewhere that Java 9 modules will solve exactly this, as only the required parts of libraries are loaded, and significantly on the used parts of the standard library.
The JVM already does that - it only loads things it needs. So you can have a 2M dependency and only use one static function of a single class in there, and it will only load that - but you have to distribute the whole JAR. With Jigsaw, things are split up, so you can have only the stuff you need.
It's disk I/O. The JVM basically loads classfiles one at a time. When you use Spring Boot, you are asking Spring to pull in potentially thousands of such classes.

Preliminary tinkering by Spring folks shows Graal having a substantial impact there too.

Long JVM startup time is a big reason why I went with Elixir instead of Clojure when I decided to move off Ruby to do webdev. (Another reason was easily triggering nasty Java stacktraces.)

My Elixir test suites fire up instantly and finish in seconds (if that) and this fast-as-possible feedback loop is extremely important to stay productive, IMHO.

The editor based REPL is how the Clojure folks stay productive (as opposed to running tests at the command line). Using a keyboard shortcut to eval any expression in your code is really great.

The stacktraces are still often terrible though =/

Clojure startup time is only partly related to JVM startup time, which is ~60ms[1][2]. The reason Clojure startup is slow is because Clojure requires a very elaborate initialization. OTOH, the Erlang VM (BEAM) is much, much, much slower than the JVM (Hotspot, at least).

[1]: https://blog.ndk.io/clojure-bootstrapping.html

[2]: http://clojure-goes-fast.com/blog/clojures-slow-start/

Cant you just have a system clojure process started up and then fork from there?
Forking, in general, is not a very safe operation when the process is an elaborate one, like a JVM. It may, however, be possible to have Graal compile the Substrate VM image for Clojure after the initialization has been done, dumping the initialized state to the image, and then just loading it on launch. This may be the solution chosen once Graal matures a bit, and people learn how to use it well.
Forking is easiest and safest in a functional-data-structure immutable language (where it's basically trivial). Mutable languages? Not so much.
With Clojure you get that feedback loop by running everything in an open repl. No startup time needed.
so you rerun tests in a REPL? what happens when something is redefined?
Typically Clojure apps are structured to be reloadable meaning that you don't have any global state, and you can easily flush the current REPL state http://thinkrelevance.com/blog/2013/06/04/clojure-workflow-r...

There are also tools like lein-test-refresh https://github.com/jakemcc/lein-test-refresh that figure out what needs to be reloaded automatically. You start it up, it watches your namespaces for changes, and reruns tests as needed. As a bonus it can even hook into your OS notification system and let you know if any tests fail.

A lot of editor integration will handle reloading and test-running for you (including VSCode's calva extension, Cursive, and Proto REPL for Atom, although it's less "automatic" than the others).
I've found cdi starts much faster than Spring these days! Glad to see it catching steam
ah this is great. I need to look at switching to Graal.
Graal can be used as the JIT compiler got your JVM. It's also pretty easy to hack on. There a great presentation on YouTube by one of the project leads about that.
To the author: https://www.youtube.com/watch?v=OonDPGwAyfQ

In other words, thank you for the content, but this could really use some proofreading.

Guilty as charged :-)
Thank You. This is a good video to drive the massage.
Nothing like a good massage!
related: "Why is the title of the book The Medium is the Massage and not The Medium is the Message? Actually, the title was a mistake. When the book came back from the typesetter's, it had on the cover 'Massage' as it still does. The title was supposed to have read The Medium is the Message but the typesetter had made an error. When McLuhan saw the typo he exclaimed, 'Leave it alone! It's great, and right on target!' ..." https://en.wikipedia.org/wiki/The_Medium_Is_the_Massage
wow, that video was amazing! forwarded to some writer/editor friends. thanks!
BTW - CLI-matic uses your excellent Orchestra.
That's both superb and encouraging. Thank you.
"So you have no excuses not to build your CLI tools in Clojure now."

Except that the toy program is 25MB and takes multiple minutes to compile...

25 MB almost fits on a floppy disk! That's acceptable to avoid dynamic linking or external dependencies. And that 25 MB is a fixed-cost (a JVM-subset, libraries, etc) and as the app adds functionality the fixed 25 MB cost becomes less as a percentage.

It's not viable for built-in Linux tools, etc. But for a custom tool where performance matters, it's a great solution.

... and the multiple minute compile is only for _release_ builds.
That and you are using proprietary Oracle tech.
The CE?
Yes. It's not like it's donated to the OpenJDK community or anything even though they are going to start shipping with it. It may not affect you and you may not mind, but I personally avoid software owned by that company when I can (which is of course not always). I am also always wary of developer languages/libraries that use the freemium model.
GPL + classpath exception seems to be about as free as it gets.
If you're responding to my comment about the owner, we cannot tell what the future will hold, we can only judge by the owner's past conduct. If you're responding to my comment about freemium, the concerns aren't the current license of the free version, but the decisions that come about when there is a monetized and non-monetized version. While it's often reasonable in other forms of software, in developer languages/libraries I think it is dangerous to build reliance on anything with that kind of conflict.
It's Open Source: https://github.com/oracle/graal

I made a very small contribution (removing 4 incorrect quote characters from some sample JSON code)

> It's Open Source: https://github.com/oracle/graal

Sure. That doesn't change my statement though.

(comment deleted)
> Proprietary software is non-free computer software for which the software's publisher or another person retains intellectual property rights—usually copyright of the source code...

https://en.wikipedia.org/wiki/Proprietary_software

Which is the case here for Graal (there are differing definitions of "free"). From your link:

> While most proprietary software is distributed without the source code, some vendors distribute the source code

Source code available, or even under an open source license, does not change whether it is proprietary.

Not sure this is the best place to discuss the nuances of these terms. Essentially, they retain the IP, have shown a willingness to go after those doing things like re-implementing it, and in general should give people pause about using tech owned by them.

You can use it under the terms of GLP 2 w/classpath exception, which is what Google eventually decided to do. I'm not defending Oracle's business practices, just saying that Java and Graal are both Open Source™ and could be maintained by the community completely free of Oracle under the terms of GPL 2 w/classpath exception.
If you are referring to Java, I would point out:

Oracle's JDK is based on Open JDK.

Open JDK is licensed under GPL + the classpath exception. (eg, the Open JDK is under GPL, but when used as a runtime for other software, then that other software does not come under the scope of the GPL.)

There are multiple other sources to get pre-build binaries for the Open JDK without going to Oracle.

Azul Zule built for multiple platforms including Linux, Mac OS, Windows.

https://www.azul.com/downloads/zulu/

And Zulu for Raspberry PI:

https://www.azul.com/downloads/zulu-embedded/

Open JDK Build:

https://github.com/ojdkbuild/ojdkbuild

(click the 'releases' link)

Adopt Open JDK:

https://adoptopenjdk.net/index.html

(offers choice of HotSpot or IBM's Open J9 technology)

There's also Red Hat, for free, but you must create an account.

And IBM makes their own builds, but they are typically bundled with some other product such as Eclipse, so a bigger download.

lol, and I thought my 5MB golang binary was huge!
strip it
I use upx if I don't plan on having binary patch updates.

But I wanted to be fair with the article.

Well, to be fair with Go, I should say 2MB for an hello world app like the one they have.

The hello world app has Clojure Schema and Orchestra validators built in, that's not very simple (though you don't see it).
If you really want to script in Clojure you should probably use Lumo https://github.com/anmonteiro/lumo . Starts up almost instantly (including a repl!). Still wouldn't recommend. But it's workable.
Looked into it, but the big thing of my scripts is that they often use JDBC or http-kit, so cljs would not be as good.
"6G to 8G RAM" to compile. A real win then.
This compilation step is only required once when you release your tool. The resulting binary is then providing fast startup and low memory footprint whenever users invoke your tool. So, yes, it is a real win if your tool gets used more than once.
Or use like lots of other languages that provide all these "wins" without having to provide justifications like "only for release build and if your tool gets used more than once".
I spend most of my time actually programming in the language, not compiling it. So, I'm going to optimize for that, but to each his own I suppose.
It's not an either-or, you can have both.
I can't really think of a language that I'd rather use than Clojure right now. So, I'd have to get these "wins" I'd have to switch to working with a language I enjoy less.
Why cannot Java probuce binaries that can be mapped into memory and shared like native executable files? It could solve the startup time problem.

Google even had to invent a zygote process in Android to make apps start faster.

> Why cannot Java probuce binaries that can be mapped into memory and shared like native executable files? It could solve the startup time problem.

It can. That’s what this article is about.