5 ms·
Hypothetically, if you could daemonize javac, would JIT eventually kick in over multiple recompiles of the same code? The obvious use case for this would be IDE
by alisonatwork 1y ago
Hypothetically, if you could daemonize javac, would JIT eventually kick in over multiple recompiles of the same code? The obvious use case for this would be IDEs, but I imagine it could work in CI too if you had some kind of persistent "compiler as a service" setup that outlived the runners.
Not to detract from the cool work done here, just curious if this other approach has been tried too.
- sgammon 1y ago> Hypothetically, if you could daemonize javac, would JIT eventually kick in over multiple recompiles of the same code? This is actually how Gradle works by default; in fact, even if you pass `--no-daemon`, it will start a daemon, and just kill it after the build (lol). It's daemon-first, daemon-only, because of this exact issue. As I understand it, Gradle's daemon timeout is typically 10 minutes, but can be extended. We are guessing that this style rarely hits the 10k class threshold where JIT performance converges with native, especially since Gradle also supports incremental compilation, and that further impedes the progress toward a warm JIT. Gradle focuses hard on build caching and incremental compilation, and this is conceptually in contention with reaching a warm JIT, ironically. Native Image has JIT capabilities (just not as mature as Hotspot yet), and keeping the daemon alive would probably still yield wins. We haven't tried it yet and that's a good idea
- alisonatwork 1y agoI'm aware of the Gradle daemon, but wasn't sure if it only handled dependency resolution and other build orchestration tasks or if it also ran the compiler in the same JVM instance. Last time I worked somewhere using Gradle I think we forked the compiler anyway to ensure the project was built on exactly the same Java version regardless of what the Gradle environment was running in, so in that case there is definitely room for startup optimization. I do recall the Gradle daemon living much longer than 10 minutes, though. The docs say 3 hours is default, although if really trying to maximize the JIT advantage it perhaps would make sense to keep it alive as long as possible.
- sgammon 1y ago> or if it also ran the compiler in the same JVM instance Honestly, Gradle's toolchain resolution mechanisms have changed so much, it is a little hard to keep track. Good point > The docs say 3 hours is default Huh, I'm not sure where I got 10 minutes. I'll research some more about these assumptions, but even so, having used Gradle professionally and personally for many years (like you), I wonder how often I would have hit that threshold. I was mostly working in smaller projects and companies, though, so my experience could be different from the norm. Even assuming engineers hit that threshold, it would be toward the latter end of that window and only until the end of that window. An experience optimized for cold-start and non-reflection balances this approach, and is even build-cacheable with standard tools like sccache. There are still a lot of projects where JIT-based javac would be optimal > perhaps would make sense to keep it alive as long as possible It would for sure. I'm not sure why Gradle was never able to execute on Bazel's full vision for remote execution. Probably a hermeticity problem, considering the challenges they already seem to face with e.g. the configuration cache. In any case, this is great feedback, thank you :)
- alisonatwork 1y agoI work professionally in Python these days, but I've just spent a bit of time digging into the contemporary situation because the JVM environment is much more interesting to me, and found this spec: https://build-server-protocol.github.io https://build-server-protocol.github.io Seems the Scala guys have doubled down on the "compiler as a service" approach, presumably because their compile time story continues to be painful. But also looks like the same solution is used for the VS Code Java/Gradle integration, so seems like this might be the more conventional way to go for traditional JVM projects. For processes where the JIT takes a while to kick in, but also you don't want to waste memory keeping JVMs alive while not doing anything (and compilation could be a good example of that), I wondered if there was a way to snapshot and restore the JVM state and turns out some people are experimenting with that too: https://openjdk.org/projects/crac/ https://openjdk.org/projects/crac/ It's all neat stuff!
- sgammon 1y ago