|
|
|
|
|
by amarant
1 day ago
|
|
I do agree that as far as VM's go, the JVM is not bad. I guess my recent fascination with rust is kinda shining through here, but I've begun questioning the need for any sort of VM: even the best ones add overhead, and since in practice we always deploy to a very specific environment anyway (when was the last time you deployed a non-dockerized jvm app?), why not just build native executables and skip the overhead? I dunno, I feel like I'm deploying a VM in a VM in a VM, and at some point they cost more than they taste. |
|
Nope. Quite the opposite. You can precompile Java to a static runtime using the likes of Graal or even android. That actually makes these applications slower, not faster.
Part of this comes down to the Java language design. For Java, there is a lot of dynamic dispatch involved. In rust terms, it's as if almost every parameter was a `Box<dyn Foo>`. In Java, it's pretty natural to have a method like `void foo(List<Bar> baz){}` which can be called by any concrete list type. In fact, compiled down, this actually looks like `void foo(List baz) {}` in the bytecode.
The JVM is able to capture runtime information and realize "Oh, `foo` is always called with an `ArrayList`. And that `ArrayList` always emits a `Bar` element." That allows it to optimize and directly call the `ArrayList` methods rather than having to always do a "Ok, determine the type, look up the method table, call the method". Which is exactly what rust has to do with a `Box<dyn Foo>` signature. To do something similar with Rust you have to do a more complex PGO compilation.
Now, don't get me wrong, rust is smart. That's why they've designed the language such that `foo: Box<dyn Foo>` just isn't as ergonomic as `foo: &Foo`. The language pushes you to use the concrete structs when possible and to avoid doing dynamic dispatch. It supports it, but it requires a lot more ritual.