And here we are, 20 years later.
And here we are, 20 years later.
To this day, Java applications are the slowest and most memory hungry long-running server applications by far. Only some scripting languages are worse, but only by performance, almost never by memory.
I am not a fan of Java, but the slow part is just plain wrong. On properly sized hardware Java is blisteringly fast. Did it exceed the speed of C as hyped? No, in most cases it falls solidly short, but I'm sure there are isolated cases where it does. Regardless, 2-3x slower than C using a JIT is a serious feat of engineering.
All GC languages require more memory, and Java is even worse given lack of value types, but again, memory/hardware is cheap compared to programmer time and if you have enough of it, it generally isn't a problem.
All this does mean you will need a bit more hardware than a C program, so perhaps that is the posters critique, and that is true, but compared to other high level languages, it does great in the speed dept, and is often only a bit higher in the memory dept.
Your second paragraph is just thoroughly uninformed, though. And unused RAM is useless, so in a server application not making use of it is just dumb. Maybe think about why Java is used extensively by pretty much every FAANG company. Also, Java has improved steadily after Oracle's takeover, and is in fact the open-source reference implementation. Again, uninformed bullshit.
Java programmers are a dime a dozen. Universities churn out heaps of Java code slaves, so of course every big company will use Java for their shovelware.
https://kstefanj.github.io/2021/11/24/gc-progress-8-17.html
Note: this is comparing to Java 17 to Java 8 (released in 2014), and we are now at Java 24!
There are no serious Java performance comparisons on stuff like transaction throughput, which would be what the "long running server application" usecase should aim for. You yourself claimed that enterprise data processing is what you are talking about. There are benchmarks that even with long warmup times make Java come up far worse than all the compiled languages (even Golang nowadays). https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
Imho, people have stopped benchmarking Java ages ago, since it is known to be hopeless.
GC usually also comes in "copying" variants, which can have advantages like reducing memory fragmentation.
Memory fragmentation can more easily be reduced by pooled allocators. For long-running server processes, it can also be possible to just kill the worker processes/threads from time to time. And I've never seen memory fragmentation in manually allocated languages lead to more memory consumption or worse performance than in Java.
Here is your transaction throughput. But I'm sure AWS's whole platform team, Alibaba, third of Google, etc don't know what they are doing.
If you exclude stuff like SSE intrinics, it's usually 50% slower.
What about the median performance benchmark tasks?
https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
No idea how you got that impression. Here is an incomplete set of important changes:
- major developments on Graal and native code compilation for applications that prioritize startup time and memory use (I think Graal was started before 2011, but has changed a huge amount since then).
- the concurrent G1 garbage collector became the default, making most applications have much lower pause times (I believe it was released in Java 7 in 2011, but was not mature, only became a default in Java 9, and has regular improvements since then).
- the Shenendoah and ZGC concurrent garbage collectors were not started until well after 2011
- project lilliput, which reduces the header size of Java objects from 16 to 8 bytes is landing in Java 25, which comes out this fall
- specializing strings to use 1 byte/character for ascii strings, and 2 bytes for non-ascii strings
- virtual threads shipped in Java 22
- work on a vectorization API
- plenty of work on reducing the startup time of the JDK and modularizing it
One where I'm not sure about the timeline:
- https://docs.oracle.com/javase/8/docs/technotes/guides/vm/cl... class data sharing to lower overhead of running multiple JVMs on a single node
P.S. I'm not writing this to comment on the the parent's claim that Java is faster in some contexts.
> Yes, Java can be faster in certain contexts: the kind of contexts Java is usually employed in addressing these days. Stuff like enterprise backend systems and big data processing, where startup time or precise memory control are not important.
The only thing that might be relevant in your list is the vectorization API.
The rest of your list is just a bunch of band-aids for the worst problems that Java specifically has, that other languages lack. That is at best playing catch-up with everything else, since in C there is no GC overhead, almost no startup time, no object overhead, no GC-induced memory hogging, no GC pauses. Yes, I agree that things did happen. But nothing in there makes Java any more desirable for relevant workloads, it just makes it less undesirable.
Are you even aware of the word "tradeoff"?
And in particular that garbage collection can be faster than malloc/free.
This is technically true in the case you have a naive C program. There are tons of C programs out there, and some are slow. (But there are more slow Java programs out there)
But it's 100% clear now that GC has a significant cost, and while you can optimize a bad C program, it can be very hard in many cases to optimize the cost of GC away.
C offers more freedom and thus more footguns, but the freedom also means you don't really have a performance cap.
And I prefer GC -- most programs I write will have GC; I just recognize the performance cap, and design accordingly. (In fact I wrote a GC for a subset of C++ for https://oils.pub -- I actually think this is a language with nicer performance properties than Java, mainy due to being AOT)
I will very easily write a faster parallelizable program in Java, before I get the C one even remotely correct and then we haven't even taken into account every future maintenance cost. Also, the way C devs often hide the cost is simply.. less efficient code like copying stuff right and left, etc, which can actually be more "bravely" avoided in managed languages.
The reality is that it's quite the opposite. Java boxed types, lack of control over memory layouts leading to page flapping and false sharing, lack of fast synchronisation primitives, lack of a compiler capable of hinted or automatic loop parallelization lead to Java being totally unsuitable here. The crown goes to FORTRAN in that regard, with C and C++ being second and third places.
Of course theoretically a magic fairy-tale Java compiler could look at the code, recognize all the aforementioned problems and fix them. Of course the language would allow for this to happen totally without changing semantics. But no Java compiler even comes close...
Even better in Rust. You get great memory safety guarantees from the borrow checker helping guide your parallelization, while still being fast and GCless.
It's the best of both worlds.
>Also, the way C devs often hide the cost is simply.. less efficient code like copying stuff right and left, etc, which can actually be more "bravely" avoided in managed languages.
I'd say Rust is again the easiest way to avoid unnecessary copies without sacrificing safety.
For certain other kind of concurrent algorithms, you are in a world of pain and Rust's borrow checker simply refuses to compile a large set of otherwise correct programs.
Especially profile-guided-optimization was hailed as the next big thing, only JIT-ed languages were the ones to be fast, because after some warmup time they would adapt to your data and hardware. Java is still dog-slow...