4 ms·
I understand your point, but I disagree with the characterisation of 'compiled versus interpreted' (which I've seen elsewhere in blog posts too). Java, C#, etc
by chriswarbo 5y ago
I understand your point, but I disagree with the characterisation of 'compiled versus interpreted' (which I've seen elsewhere in blog posts too).
Java, C#, etc. are also interpreted languages; they just-so-happen to have a separate compile-to-bytecode step (unlike e.g. Python, which compiles to bytecode when a file is first imported); and their interpreters just-so-happen to have very slow startup times.
"Compiled languages" can have very fast startup times, if we avoid languages like Java (which sacrifice a lot of startup time in favour of steady-state throughput; which is obviously inappropriate for a Lambda). If we do compile down to a native (x86_64 Linux) binary, it requires a custom runtime (e.g. if using Haskell, Rust, etc.).
- brabel 5y ago> and their interpreters just-so-happen to have very slow startup times. I was surprised to find out that Common Lisp (SBCL) is so incredibly fast to start up that it can run faster than Rust even starting from source. And Lisp is the archetypical dynamic langauge! Made me question my entire career working with JVM-based languages.
- lispm 5y agoMany Lisp systems like SBCL basically restore the main memory (heap) with all data, caches and native code. Then they call a start function. No need to load/link/compile/initialize code at start.
- Zababa 5y ago> if we avoid languages like Java (which sacrifice a lot of startup time in favour of steady-state throughput Could you expand on that? I understand that both the JVM and Node are JIT compilers, but I don't understand why the JVM usually takes longer to start and what are the trade-offs involved here compared to Node.
- chriswarbo 5y agoThe main differences are probably the compilers involved, which tend to be layered based on how often a routine gets called (starting interpreted, then using a fast-but-dumb JIT compiler, then a slow-but-smart JIT compiler). There are many JVMs, each operating slightly differently, but the HotSpot JIT seems to be the most widely used (e.g. https://cl4es.github.io/2019/11/20/OpenJDK-Startup-Update.html https://cl4es.github.io/2019/11/20/OpenJDK-Startup-Update.ht... ) Node runs on V8, which is described in more detail at https://v8.dev/blog/ignition-interpreter https://v8.dev/blog/ignition-interpreter Another big diffence is that Java does lots of special handling for classes, e.g. hooking up 'reflection' machinery, allowing dynamic 'class loaders', etc. which happens during an application's startup. In contrast, Javascript 'classes' are basically just functions (constructors); and Javascript functions are values just like anything else; hence there's less of an up-front cost to JS code. Python works in pretty much the same way from a language level (but its CPython interpreter works very differently to V8).
- jollybean 5y agoThis is not the type of answer you want, but it is the answer: Java/JS startup times are different largely for product reasons. V8 is highly optimized for fast startups because that's necessary in loading web pages. JVM startup time is generally not an issue anywhere but Lambdas, also, JVM apps run for longer and so they want to take advantage of performance data to optimize over time. If Oracle was desperate to make JVM start fast as a matter of life-or-death for an important revenue stream, then JVM would start quickly. What the trade-offs would be I don't know, but keep in mind there might not have to be any, at least materially. Products are made to do certain things and not others, if something was never a requirement, nobody ever cared to think about it hugely material terms, well it's unlikely to happen. FYI one simple tradeoff is that JVM might not compile code until it's run a bit and optimized whereas V8 might immediately compile some things meaning the later you get 'pretty fast right away' but miss out on the runtime characteristics that make it optimally fast, so in the former you pay a little bit of 'learning time' up front and then get better optimization.
- nirvdrum 5y agoOracle has a Java AOT compiler as part of the GraalVM. They call the feature native images [1]. It's not quite the same thing as configuring functionality in the JVM to see what speeds things up, but I think it'd give a good idea of what would need to be dropped for faster start-up time. The biggest one is dynamic class loading. [1] - https://www.graalvm.org/docs/getting-started/#native-images https://www.graalvm.org/docs/getting-started/#native-images
- jollybean 5y agoAOT is actually often slower than the JVM because it doesn't have runtime profiling. It is possible to use AOT with runtime profiling (i.e. run your app in some real world manner, capture the data and then AOT with the runtime data). But the point here is that JVM (and V8 actually) can do more than simple compiling by understanding the nature in which the program runs and therefore be quite fast often making up for the fact they are VMs.
- twic 5y agoThe JVM doesn't, it starts in tens of milliseconds. But many popular Java frameworks take seconds to start (i believe mostly because they make heavy use of reflection and classpath scanning). You can write fast-starting Java apps, but you have to stray away from the beaten path to do it.