Hacker Read top | best | new | newcomments | leaders | about | bookmarklet login

Right, but the problem is that many programs do a lot more work when they start up than Hello, World. The Clojure runtime in particular does quite a lot at startup.


sort by: page size:

A "hello world" Java program starts up fast, sure. But Clojure start-up time usually takes more than 1 second; it can be 10 seconds plus if you include many jars. I don't know whether that's more the fault of Clojure or the JVM.

That article is disingenuous, the startup time of "hello world" in Clojure is still pretty bad but tolerable, the issue arises when you start to add libraries, now your web service can take from 1-2 minutes or more to start.

It's true that Java hello world will be faster than Clojure JVM hello world. That said, a big Java application with lots of classes to load, and lots of static initializers (which would approach the same number as what Clojure requires to be loaded and initialized) would take as much time as it does for Clojure.

So when people say that part of the slow startup is Clojure's fault, they mean more that it is implemented in a way that the JVM isn't very fast at starting. But if you look at Clojure implemented on other runtimes, like ClojureScript, the startup times are much faster, because the NodeJS runtime is much faster to start and initialize everything than the JVM is.

In effect, if the JVM improves startup times, so will Clojure JVM's startup times be improved. That's why I see this drastic difference between a Clojure hello world on Java 8 vs Java 14.


Startup time is something of a red herring for me, kind of like "give me a single EXE or your language is useless" used to be in the Common Lisp world. I don't encounter this problem in practical use. But then, I don't use Clojure to write scripts that I then run hundreds of times from the shell (but why would you want to do that, rather than write a program that does what is needed to hundreds of files at once?).

Interestingly, Java and Clojure have decidedly different startup times on my machine.

A trivial hello-world in Java takes ~130 ms on my Debian sid box with « OpenJDK Runtime Environment (IcedTea6 1.8.7) (6b18-1.8.7-4) / OpenJDK 64-Bit Server VM (build 16.0-b13, mixed mode) ». This is with all default runtime options.

The program « (ns hello (:gen-class)) (defn -main [] (println "Hello, world!")) » compiled with Clojure 1.2.0 (again from Debian sid) takes ~1700 ms. Using -Xbootclasspath takes it down to ~800 ms. -client doesn't do anything obvious. Unpacking the Clojure JAR increases the time.

So presumably there's something about pulling in the Clojure runtime pieces that is very slow, but I have no idea what it is.


I guess you are not familiar with Clojure, it adds a lot overhead over the overhead of the JVM to startup time.

> Also, seems the JVM is slowly improving in startup time department.

It's not the JVM that makes Clojure JVM slow to start up, try comparing hello world in Java vs hello world in Clojure.


Sure it's a lot, but clojure startup times are significantly longer than that.

I don't really care about startup time personally but the linked page mentions "very low memory usage" which is quite a contrast with Clojure which seems to use insane amounts of memory for simple things.

I think what's missing in your parent but assumed is, within the context of Clojure, startup is slower than ClojureScript. The Clojure runtime is relatively slow on startup.

Clojure startup time is less of an issue with clojurescript. The idea is is you start the compiler and run it in watch mode.

Sure it's a disadvantage, but the way you say it makes it sound like it results in a terribly slow development experience where you're constantly waiting for it to start.

The truth is, the development experience actually gives you much faster feedback with almost no waiting time as compared to the majority of other languages.

That means the impact of the slow startup isn't really felt.

I think where slow startup is a bigger issue is actually for certain production use cases, like CLIs, or serverless settings. There it would be awesome if Clojure JVM also started in sub-millisecond, and we didn't have to change to Clojure interpreted like babashka, or Clojure GraalVM native compilation.


Java’s startup only slows down when a ton of classes have to be loaded, e.g. that’s why Clojure’s repl takes quite some time as you are loading two standard libs.

For a simple hello world it is below 0.1s.


Most of the Clojure app startup time (~1.2s on my machine) is the Clojure runtime, not the JVM (usually less than 100ms).

What most people seem to miss is that if you use Clojure, the startup time hardly matters, because you do not restart your development JVM often.

I find this similar to discussions about boot time. It doesn't matter -- I reboot my computer once a month, if even that.


You're suggesting the answer to "we need better startup time" must be "we need the best startup time possible"? In that case, Go is also bad. Everything should be hand-rolled assembler.

Many of us who actually run Clojure in production have been bit by this, and Clojurescript has been fast enough to alleviate the issue. Not a straw man, a community meme.


But noone cares about hello world. You're not building hello-worlds in real life.

Slow startup time is a problem in automated testing of big codebases - when you aim to test the whole codebase, but each test alone does not stress any code path hard enough for the hotspot compiler to kick in. So basically most of your Java code in testing runs in interpreted mode, which is like 20x-100x slower than properly compiled and optimized C/C++/Rust.


Your understanding is correct. JVM startup accounts for a small portion of Clojure's startup time.[1] Most of the overhead is in compiling and loading clojure.core. Efforts have been made to remedy this issue[2] (e.g. direct linking, ahead-of-time compilation, ...), but this doesn't remove the fact that clojure.core is huge and virtually any Clojure program will be importing more than just clojure.core, so there is still a lot of var derefs to deal with, then code to compile, then classes to load, etc.

[1] https://clojure-goes-fast.com/blog/clojures-slow-start/

[2] https://clojure.org/reference/compilation


The JVM cold-starts, loads a Hello, World program from a compressed JAR, runs it and shuts down in 40ms. But Clojure compiles quite a bit of Clojure code generating hundreds if not thousands of classes and then loads them before starting up the Clojure program. Still, there's ongoing work on the JVM (Project Leyden [1]) to speed up both startup and warmup even of such programs by caching more state.

[1]: E.g. see https://spring.io/blog/2023/10/16/runtime-efficiency-with-sp...

next

Legal | privacy