Bad deployment system. You should do an A/B deployment and warm up the services/caches before the switch, so that the architecture handles the problem and not the programming language/VM.<p>At FastComments we run our E2E tests on the new instance to JIT the app. Before the Jit API calls can take 100ms, and after 10-30ms. Still, that is fast enough that most people wouldn't notice...<p>Also, the problem is not Java. Your application probably has way too many abstractions for a simple login page.
>Molding a 25 year old runtime ecosystem to adapt to AOT compilation feels like putting lipstick on a pig.<p>Other JVMs like J9 have had AOT support for decades now, its not "lipstick on a pig". There's plenty of material from previous JVMLS meetups about AOT.
The article's "container lifespan" chart shows that 21% of containers live less than <i>10 seconds</i> and 54% live <= 5 minutes. If the base data set has that many very-short-lived containers, it's probably not representative of containerized persistent services. How many services get CD updates every 10 seconds?<p>Indeed, the original Sysdig report that the chart comes from makes this case:<p><a href="https://sysdig.com/blog/sysdig-2019-container-usage-report/" rel="nofollow">https://sysdig.com/blog/sysdig-2019-container-usage-report/</a><p>"Many containers need to only live long enough to execute a function and then terminate when it’s complete. Seconds may seem short, but for some processes, it’s all that is required. We believe the increased use of Kubernetes Jobs that run finite tasks like batch jobs contributed to this growth. In fact, we expect short lifespans to increase, especially on serverless platforms that are well-suited to running short term tasks."
Kotlin methods are final by default unless marked open, and thus nonpolymorphic dispatch unless through an interface.<p>It sounds to me like the problem isn’t the VM it’s the insane amount of framework code you have to be initialized. This can be optimized with Java via class data sharing and snapshotting but if your code is all written in Kotlin and you toss Spring into the trash can In favor of say, Dagger or hand crafted DI, most of your problems would go away.<p>Besides, Kotlin/Native can compile and run without a VM.<p>See <a href="https://august.nagro.us/jvm-startup.html" rel="nofollow">https://august.nagro.us/jvm-startup.html</a> for examples of how to optimize startup without Prewarming JIT.
This is about runtime binding vs static binding, not static objects or static members. There is still a "this", but the code that will run is known up front -- "ahead of time".<p>C++ went through this 25+ years ago: runtime binding, what in C++ is virtual functions, is a <i>niche technique</i>. Most C++ programs don't use it at all, or use it in only one or two spots. When it is the right thing, it makes the work convenient, but it really is just a dance with function pointers. In C++, templates do the heavy lifting.<p>Java never offered any other support for organizing programs, so inheritance and virtual functions have been your go-to for everything, no matter how bad the fit. In a static call there is only one bit of code to run, and it never changes over the life of the program. Just like <i>almost everything</i>, really, except here your runtime knows up front.<p>It was always a dumb choice to make member functions default to virtual semantics, when they almost always don't need it, and it just costs performance to no purpose. That is what comes out of treating language design as a marketing exercise: Java's designers really (and openly) cared less than nothing about object-oriented programming. They thought people really ought to be coding Lisp. Forcing runtime binding was a way to sneak in something a little bit lispy, and maybe get people used to production code running no faster than Lisp.
Others have raised good points, but seriously something is wrong if you’re pushing updates that require restarts every hour.<p>I get the idea of “continuous deployment”, but this is sounding like restart-per-commit. At that point I question how much qualification and validation is happening. No one say unit tests, they aren’t sufficient, and I’ve worked on multiple projects where the pre-commit test suite runs alone can take more than an hour. Even with those tests there are semi-regular breakages.
> 74% of containers have lifespans ≤ 1 hour<p>This sounds like a design flaw in the architecture. You don't tear down a house to replace a lightbulb.
> Production Java apps also typically run with APM tracing agents that rely on runtime bytecode instrumentation. [...] It is easier to start afresh with modern compiled languages like Go and Rust.<p>I wonder how they instrument their Go and Rust programs. If they decide not to, maybe it's not that important for the Java version of the same code either.
Every serious Java based Web App I've ever worked on had a prewarm step or continuous probing setup for exactly these issues. It isn't unique to Java either - lots of languages have lazy library or dependency loading, or runtime caching of external files or the like that you want to do before you start serving requests.
> Go and Rust encourage use of static method calls<p>Not having worked in Go or Rust but having done a lot of work in Java and C/C++, I'm curious how this works out in practice. My experience with developers who default to static method calls rather than objects in Java or C++ is that they also default to static (and therefore global) data as well. Of course, you don't have to do that: you can pass pre-transaction data structures to the static functions and let them operate on them, but that's what object-oriented programming is for in the first place.
TL;DR; A company that sells Go consulting services bad mouths JVM JIT while completely ignoring JIT caches and AOT compilers that exist since around 2000.