| In what world is Go more reliable or faster than Java? Especially modern Java (or other good JVM languages like Kotlin). It compiles faster but that is about it. Which is a good thing too because it's verbose AF and heavily reliant on code generation even after generics shipped so that compiler lines/s actually matters. The only knock you can put on Java for reliability is null-safety but lets be real, nil pointers, bad slice initalisation, etc are 10x worse in Go especially these days with @NotNull and powerful editors like IDEA stopping you from doing dumb things. Or simply using Kotlin which is non-nullable by default. That and all the things Go is good at Java is simply better at. (especially once Java 21 ships in the next few days). - Low pause GC? ZGC has Go beat, not just on pause times but on throughput and heap size scalability up into the terabytes.
- Non-blocking code with synchronous coding style? Virtual Threads are much much better than goroutines.
- Channels? ArrayDeque and friends are faster and have a lower learning curve. Maybe the only area I think I prefer Go to JVM-land is the good parts of the stdlib. Go has lots of shit stdlib cough collections cough but there are some real gems. Namely the x509 and ASN.1 libraries are absolutely top notch. Learning curve is also lower ofcourse, it's a very very simple language which is good for beginners and those taking their first steps out of JS/Ruby/Python into static types, pointers, etc. Anyways, my real point was Java is easily faster and more reliable than Go and it seems pretty insane to reach the opposite conclusion if you have been on top of developments in both languages. |
That said: A few design decisions in the Java language (that are only slowly getting fixed) harm performance:
1. "Everything is virtually dispatched" reduces the ability to make inlining decisions sensibly. 2. Escape analysis gets harder (and less effective), leading to moving fewer variables onto the stack. 3. The poor support for allocating compound data types on the stack.
All of these conspire to create many more heap allocations than comparable Go code, so even if the GC is much better, the amount of work it has to do is much bigger.
Achieving any form of data locality in Java is also hard because it's really hard to nest structs.
The Java design shows that the memory wall wasn't a thing yet when the language was designed...
Things are slowly getting fixed, and there's a lot of interesting off-mainstream stuff that can be done to get more perf in Java-Land (Azuls JVM, Graals AoT etc) - but the strange thing is that Java does pay for some outdated design choices while Go performs pretty well despite a very simplistic implementation...