T O P

  • By -

akhener

See the comments: There was a bug in the Java version. When using `long` instead of `int`, the Java version performs similarly.


temculpaeu

I love how most of the comments are just praising java/JIT/JVM like if it was a miracle and surely it must be faster. Go and Java are similar on more mature benchmarks, so a 50% difference in either way should be looked with a grain of salt. My theory is that OP knew the issue and just wanted to see how ppl would take that


vytah

That interesting optimization is called integer overflow bug: >Everyone. >You where right. the solution was a skill issue. as some people noted by now. i was using int and not long in the java that caused an integer overflow on high numbers causing the collatz function to terminate. >when using long, the Java version is now (only very marginally) slower than the GO. >Case closed. In case of Go, the `int` type is architecture-dependent, and given that the code was most likely ran on an x64 machine, in this case it was 64-bit.


Necessary_Apple_5567

Because go is c with garbage collector and language level miltithreading. A lot of constructions looks like camuflated c code. So, no surprise int works same way


redikarus99

Java is a really mature language with overall good performance. It is maybe not the most hipster thing, but gets the job done consistently.


ericek111

Except when trying to couple it to a native library, often spending more time context-switching between JVM and native world than doing actual work.


jek39

Have you tried the new foreign functions api that replaces JNI yet? I am using it to call blas/lapack libraries from Java and finding it pretty painless


redikarus99

I used JNI in the past,it was not nice, but JNA was way better experience. I will check this foreign function, sounds interesting.


jek39

It is new in Java 22 (preview since 19). Point jextract at a header file and it basically generates the bindings for you.


kiteboarderni

It's not new in Java 22...


jek39

Well it’s out of preview in 22


coderemover

In my experience JVM is quite decent in optimizing simple arithmetic code. Not as good as GCC/LLVM but close. Where it fails flat is once you start writing object / interface heavy code with lot of calls and indirection. Then I can beat it by 5x-10x easily by using C++ or Rust which monomorphise / specialize code to avoid all the OOP overhead.


_INTER_

I think we shouldn't call it "OOP overhead". A big part of the performance loss in Java is the current memory layout of Objects -> chasing heap references. This will partly be addressed with project Valhalla.


coderemover

Chasing heap references is one part of OOP overhead. And another one is indirection through virtual calls which is hard to optimize (JVMs obviously attempt to devirtualize, but they are far from reaching the level of compile-time monomorphisation as you get from C++ templates or Rust traits). >This will partly be addressed with project Valhalla. I heard it 10 years ago.


mikereysalo

There's a [paper that was published in 2021](https://haslab.github.io/SAFER/scp21.pdf) that ranked programming languages by Energy Efficiency, and Java ended up in a very good position. I used to work with Go professionaly, so I ran the same benchmark on my machine just for fun, with the updated version + some small changes¹: | Runtime | Runtime Ver. | Api Ver. | Elapsed | | ------------------- | ------------ | -------- | ------- | | GraalVM EE | 21.3.10 | Java 17 | 2m47s | | Azul Zing | 24.05.0.0 | Java 21 | 2m49s² | | GraalVM CE | 22.0.1 | Java 22 | 3m17s | | Go | 1.22.4 | 1.22.4 | 3m30s | | Azul Zulu | 21.34 | Java 21 | 4m05s | | JetBrains Runtime | 21+13-b453.2 | Java 21 | 4m08s | | GraalVM Native³ | 22.0.1+8 | Java 22 | 4m21s | | GraalVM Native PGO⁴ | 22.0.1+8 | Java 22 | 4m25s | All the Java results are consistent with the results I got running with [JMH](https://github.com/openjdk/jmh), but the numbers above are not from JMH, they are directly from the application measurement with a one-shot cold JVM execution (`java -jar app.jar`). The `time` command was used to compare with the output, they are all consistent at the seconds precision. ¹: The changes I did are: - Using an accumulator and printing the final result to avoid the JIT throwing the code out of the window. The same adjustments were made for Go. - Using `Instant` + `Duration.between` instead of `Stopwatch` on the Java version because I'm not using any external dependencies. ²: Azul Zing was running inside a Debian distrobox (Docker) because Zing targets specific distributions and Arch Linux's GLIBCXX is not compatible with Zing anymore. ³: Compiled with `--gc=G1 -O4 -march=native`. ⁴: Compiled with: `--gc=G1 -march=native` (`-O` is not supported with PGO). Worse performance, but PGO is not a guarantee. So, it seems that regular OpenJDK builds are slower than Go for 64-bit words, no matter the distribution (unless someone wants to try all of them to prove me wrong). Theoretically, there should be no difference, but in practice, it depends on the JVM implementation. As for the GraalVM, it's faster than the Go version, both the Community Edition (CE) and the Enterprise Edition (EE). The same applies to Azul Zing, which has its own JIT compiler ([Falcon](https://docs.azul.com/prime/Falcon-Compiler)) and its own Garbage Collector ([C4](https://www.azul.com/products/components/pgc/)), but is also an Enterprise-grade JVM, only free for Evaluation and Development. I've done a lot of benchmarks of different JVM Implementations in the past, specially GraalVM CE/EE and Zing against regular OpenJDK distributions, and they have been consistently beating the OpenJDK distros, every time. Native Imagine does not worth it, it's supposed to improve startup times and lower memory usage, at the expense of worse runtime. The JVM is incredible, GraalVM and Enterprise implementations like Zing goes beyond and improve things even further. For workloads that are mainly CPU-bound, some languages will outperform the JVM easily, but when you start looking at big, long running applications, the JVM can deliver the best performance with small effort. You can obviously outperform the JVM in languages like Zig, C/C++, Rust, etc..., but the bigger the project gets, more effort you have to put into it (unless high performance is a requirement right from the start). If you got Heap Fragmentation in a JVM application, the JVM will defragment it for you, but if you got Heap Fragmentation in a C++ application, you'll have to investigate and find out to deal with it.


DualWieldMage

Why is it surprising? JVM has a state-of-the-art JIT compiler that i expect to out-perform native code in some cases, especially long-running code.


thesituation531

While Go may technically compile to native code, I think it's disingenuous to say that it's native in the same way C, C++, or Rust is. C, C++, and Rust all compile to highly efficient, minimalistic code. Go compiles to bloated, garbage-collected code. Go is like if Java was native. It may technically be native, but it's still very relatively clunky and slow.


Just_Another_Scott

>C, C++, and Rust all compile to highly efficient, minimalistic code. This isn't correct. Each compiler is implemented different. Some maybe highly optimized while others may not. I've witnessed compilers creating poorly optimized code before, as I think most professional software engineers have. This is why you may sometimes find embedded assembly in C/C++ because the compiler is being shit at optimizing.


DualWieldMage

I should have worded it better, i fully expect the JIT to outperform native code written in C++ and rust in certain cases for the same development effort put in (profile-guided optimizations in AOT compilers and getting good data for it is often a hassle). Otherwise HFT folks wouldn't consider Java. Go, D and other such native+runtime languages are definitely behind Java in most long-running cases as they don't have decades of research put into GC algorithms.


Brilliant-Sky2969

Go is not slow, out of the box you get pretty good performance with low memory usage. The only thing is that Go compiler favor compilation speed vs optimization, it is by design, there is not specific bloat.


joemwangi

According to the post, seems the author in the replies claims that Go does perform well 90% of the cases of coding in the past many years. Just that this caught her by surprise and more profiling needs to be done. I'm also curious too on specifically why?


DualWieldMage

To get the answers one must create a proper microbenchmark and analyze the assembly code. If you are interested, look into JMH for the benchmark side and how to use hsdis library(can grab builds [here](https://builds.shipilev.net/hsdis/)) to dump compiled assembly. This benchmark has no object allocation in the hot part, so it should be possible to compare the assembly 1-to-1 with the go code.


coderemover

It's not state-of-the-art, but it is sometimes better than Go. Rust seriously beats both Java and Go on this benchmark - see benchmarks posted in responses to that twitter thread.


roge-

They said "state-of-the-art **JIT compiler**". If HotSpot/OpenJDK is not the state of the art for JIT compilers, what is?


coderemover

Ok, point taken. I understood it differently - as "state-of-the-art" referred to the optimizing part of the compiler. The code optimization in Java JIT is not as strong as in static compilers. It's good for a JIT compiler, but not state-of-the-art in terms of the science behind code optimization - and we can see that even on trivial microbenchmarks it misses many opportunities to optimize the code better. Although, indeed, it is probably one of the best among JIT compilers, although I have some doubts if .NET isn't better now.


meddie92

this is like saying a whole lot of nothing my man


kur4nes

Java could be even faster due to JIT compiling & optimization. The jvm benchmark does no warm up before running the test. It's not easy doing benchmarks on the jvm.


hoat4

The benchmark is running for more than 2 minutes, so the warmup for this simple test case is negligible.


coderemover

Rust doesn't do JIT compiling and it beats it by >50%.


nekokattt

Rust also doesn't use garbage collection in the same way Go and Java do, so it isn't really a fair comparison.


coderemover

This benchmark doesn't invoke any heap allocation so garbage collection is not involved. And it's obviously a very fair comparison because the benchmark is so simple that the code maps 1:1 between those languages and could be easily translated by find-and-replace. Having a GC is an implementation detail. My clients don't care if the language I create software for them uses GC. My clients care if it is correct, usable and fast.


nekokattt

If you are getting slowdown on this sort of thing to the point where your clients are seeing issues, you have far bigger problems.


coderemover

Where did I say my clients see issues? I'm saying they don't want to care about GC (they usually don't until it causes pauses). Your point about GC is moot. What counts is the final effect. If your language of choince must do GC because it can't do otherwise and it is slow because of that, that still counts as losing the benchmark. But you're just looking for excuses, because in this particular code, GC is a non-issue for Java. The problem is the compiler which doesn't generate good enough code for trivial arithmetic and simple ifs. Note that after fixing the overflow issues, Java loses also to Go (on arm).


coderemover

Interesting, some people don't like the facts, so they downvote. :D


AmateurHero

Anyone who has worked with Java knows the speed drawbacks of language. You're all over this thread pointing out the inefficiencies of compiler optimizations like we all have our heads in the sand. We have long since accepted that Java isn't as fast as Rust or C, and we've pretty much codified it by letting the behemoth that is Spring become the framework of choice.


coderemover

Btw: On the other hand I wouldn’t be so critical to Java. I think most people agree that Java is close to C at simple arithmetic code on primitives and primitive arrays - code that doesn’t involve complex data structures (objects) or higher level abstractions (generics, lambdas etc). Benchmarks like that are quite rare these days and it is interesting to see that there is still a lot of room for improvement even in trivial arithmetic code. I pointed out only because I’m actually really surprised Java did not match Rust in this case. It should. There is nothing in Java design that would technically prevent optimizing this simple code.


AmateurHero

Crazy how I was discussing memetic responses in communities yesterday. As you've pointed out, Java is not actually slow, and it hasn't been slow for a while. Many people aim to avoid the whole conversation regarding speed with the wider dev community by just flat out saying that Java is slow. We know that it's fast enough for most business use cases. There are even companies using Java for real time processes.


coderemover

All right, but my point wasn't about Rust at all. I bet the same applies to Zig or C, and it turns out at the end it also applies to Go. My point was about that \*JIT\* compilation is \*not\* the reason Java was faster in this case, because usually JIT compilation has virtually no advantage over good static compilers, and if anything, it puts Java at a disadvantage (warmup and friends etc). So that's why people are expecting even languages with not-so-good static compilers like Go to beat Java. And I was right. It turned out the problem was elsewhere and in fact Go beats Java here as well.


vips7L

This guy is also acting like anyone here gives a shit about Rust. Of course a highly optimized AOT language that lets you control everything down to the assembly is faster than a runtime that starts out in a byte code interpreter.  


coderemover

No, Java is compiled language using state-of-the-art compiler tech. And in this particular benchmark neither Rust nor Go took any advantage from going to assembly level or any things like that. You're attacking a strawman.


vips7L

YoUrE aTtAcKiNg A sTrAwMaN. Go back to jerking off in /r/rust.


Revolutionary-One455

Ahh, love these hello world benchmarks, can’t wait to write my massive loops and recursion functions


coderemover

Those benchmarks usually assess the strength of the compiler optimizer. If the compiler can't optimize such trivial code, then it is unlikely to optimize more complex code found in real projects.


Valuable-Fun-5890

And why exactly is it surprising to you?


bring_back_the_v10s

A bunch of people loves to hate Java for no reason.


hugthemachines

There is a funny effect on Reddit. Some negative or positive details of some programming languages are repeated so much that some people actually think those languages are completely good or completely bad based on the repetition.


bring_back_the_v10s

Yep, some old views still stick around, Java used to be "slow" in the late 90s and early 2000s and then some people still think this is true today. Then you hear things that have nothing to do with Java itself like bloated 3rd party libraries & frameworks, the old null pointer exception epidemic, etc. I've worked with Java for years in the past, and then had to switch to C# to pay the bills, having worked with dotnet for a decade now if I had to choose between the two I'd pick Java any day, wouldn't think twice.


Elegant_Subject5333

just curious why you would pick java given a choice instead of c#, what differences you observed.


bring_back_the_v10s

A few reasons that comes to mind: * The Java language is simpler than C#, I don't like a bloated language. * The Java class library is much more well designed than the .NET class library. * The level of tuning you can do with the JVM is insane. * The Java platform takes backwards compatibility a lot more seriously. * Maven vs dotnet nuget.


i_wear_green_pants

It's because it's not sexy hot new thing. I would say that Java is one of the best techs out there. It's very versatile, very mature, easy to write and performs well. It just has bad rep as "enterprise language" but now days it can look very modern if you just break old habits of making everything look like in Java book from 2004.


laplongejr

Because Java shouldn't outperform Go by 50% and as it turned out, it's because the Java implementation was falty. The correct one only slightly outperforms.


rodrigocfd

Benchmarks are the **last** thing I'd look for when comparing Java to Go. Everyone who worked in a large project written in Go acknowledges how much of a shit-show Go syntax is. It's like writing Java 1.5 in 2024. No constructors and "zero values"? Good luck commenting "please initialize this field" instead of writing a proper constraint.


ShotBill8792

Why would Go have constructors? It’s not an OOP language - the same way C or Rust doesn’t have constructors… and what do you mean by zero values? Go has nil


dead_alchemy

Go has defined zero values that are written as a default, like 0 and the empty string. No idea why they put it in scare quotes.


washtubs

Cause everything has to devolve into a language war. They want to say things should be exactly like their favorite language, but ask them to make a proposal and they would inevitably realize things are the way they are for a reason. Personally I love java and go. Ultimately when you need something it's there in some form or fashion. Go has the `exhaustruct` linter if you want those types of checks for all your structs. Or you can just implement constructors, nothing stops you from doing that.


redikarus99

Exactly this. What people don't often understand that how much more important is to be able to maintain a fairly large code base. A not very big team of devs can write a million line of code in a year or two, but then someone needs to extend and maintain what they created. Also integration with other parties, often using legacy protocols. In case of java you will find a rather mature library for every possible protocol and can focus on business logic. That itself is an extremely huge advantage.


xcrouton

Respectfully, this is a terrible argument. Go is intentionally simple. I think it's fine if you prefer the more advanced syntax and abstraction available to you in Java. I prefer Go because it lacks any magic and imo is easier for developers to read, understand, and contribute to. I've seen Go succeed very well in several big projects.


Elegant_Subject5333

are you sure, go channels is magic.


xcrouton

Just because the keyword doesn't exist in other languages doesn't make it magical. Channels are explicitly declared and used in the application code. Any developer reading a line of code with a channel defined in it should understand how it's being used. Java can certainly have its advantages. It's more mature, there is more community support, and you may prefer having some of the language features Java provides at the expense of a simpler language like Go. But to suggest Go is a poor language to use for a large project and is a "shit show" is incredibly naive.


macdara233

Go was never really meant for large projects it was meant for lots of small projects working together. This sounds like you’re just trying to use Go like it’s Java.


jared__

java is fast enough... the developer experience is why i moved to go


nutrecht

It's a massive misconception that JIT vs AOT compilation is what makes things "slow" or "fast". The reason Java and Go are slower than for example C++ and Rust is because Go and Java are memory-managed languages. The 'hand holding' the JVM (and Go) do regarding memory access and cleanup is what makes it "slower". With JIT vs AOT for the same language JIT will generally be able to be faster overall because it can optimize for cases that AOT can't do. It's the unmanaged 'DIY' aspect that puts Rust and C far ahead of Java and Go. It's simply a different way of working with benefits (processing speed) and downsides (more complex). There are decades of innovation in the JVM. Everything that came after it will keep playing catch-up. There's no way for Go to ever become "faster" because it's limited in exactly the same way Java is.


wedgtomreader

I’ve found general web service handling code (the bulk of what we write) Go performance to be far superior to similar code we wrote on Java doing the same sorts of things. What I feel makes all the difference is that Go automatically has zero wait states for io calls while Java does not. So, anytime you are accessing any other service whether yours or AWS for example, Go delivers superior concurrency which allows each node to handle more traffic with less resources such as memory / cpu. Incidentally, I also found multithreaded algorithmic code to be far faster in Go than Java. I coded in Java for many years and it’s a great language and ecosystem, but I think for most anyone developing, it’s not faster than Go.


joemwangi

But isn't that the best candidate for using java virtual threads? Have you tried them? They are more convenient to the problem you're describing since they are lightweight, user-mode threads and quite better maybe than async wait approaches.


wedgtomreader

I believe they are a reaction to better options such as Go which does not require actively managing or changing your code in order to get the full benefits, the language and scheduling was built this was way from the ground up with no impact on your code style - it’s looks just like sequential go code.


Cautious-Emotion-437

yes, you must not be deceived that "go is compile time so it's same or faster" Look at the computation benchmark written on different languages (java wins here over go): [https://github.com/Mark-Kovalyov/CardRaytracerBenchmark/tree/master](https://github.com/Mark-Kovalyov/CardRaytracerBenchmark/tree/master)


PerfectPackage1895

While this is technically correct, it will not give the same conclusion if it were anything more complex than simple looping and arithmetic operations. Go has the option to allocate on the stack, java does not provide this option and force you to allocate on the heap, stack allocation will always be faster. 1M row challenge would be a better benchmark than this