5 ms·
Nice post. Interesting that the fastest Java beats the fastest Go, though they are close: AY fastest Go version 2.90s 36.2 TW fastest Java version 0.9
by jonahx 3y ago
Nice post. Interesting that the fastest Java beats the fastest Go, though they are close:
AY fastest Go version 2.90s 36.2
TW fastest Java version 0.953s 110
I would have expected Go to win. That JVM works pretty good...
- dsff3f3f3f 3y agoThe Java version does additional optimizations that his Go version doesn't do and he mentions that at the end of the post. The Java version is really optimized and is an interesting read.
- avinassh 3y ago> The Java version is really optimized and is an interesting read. is there any similar blog post on the Java optimisations?
- dsff3f3f3f 3y agoNot that I know of. I just looked at the code and the commit history but a more in depth article would certainly be interesting.
- o11c 3y agohttps://news.ycombinator.com/item?id=39467885 https://news.ycombinator.com/item?id=39467885 but it looks like there have been improvements since.
- cempaka 3y agoCliff Click did a walkthrough of his solution on YouTube: https://youtu.be/NJNIbgV6j-Y?si=Wj97f-Imw5nfIzF7 https://youtu.be/NJNIbgV6j-Y?si=Wj97f-Imw5nfIzF7
- lucianbr 3y agohttps://questdb.io/blog/billion-row-challenge-step-by-step/ https://questdb.io/blog/billion-row-challenge-step-by-step/
- neonsunset 3y agoThe more accurate statement would be is Go implementatation is incapable of accessing optimizations that exist in Java and then Java is incapable of optimizations performed by C# and C++ implementations. See https://hotforknowledge.com/2024/01/13/1brc-in-dotnet-among-fastest-on-linux-my-optimization-journey/#results https://hotforknowledge.com/2024/01/13/1brc-in-dotnet-among-...
- dsff3f3f3f 3y agoGo is perfectly capable of all of the additional optimizations that are in the fastest Java implementation that is linked in the article.
- neonsunset 3y agoUntil some time ago Go did not even have inlining profitability logic in the compiler and could only inline leaf functions, something which is worse than JVM implementations could do in...2005 or so I think? Are you sure?
- AtlasBarfed 3y agoWell the Go guy probably didn't read it because "java doesn't interest him"
- deleted 3y ago[deleted]
- parkcedar 3y agoThe fastest Java version is even beating his baseline of `cat` to `/dev/null`
- neonsunset 3y agoStill loses to .NET. On reference host Java still closer to 1.7-2s ballpark (and has to use awkward SWAR to get there) while the fastest solution in C# is 1.2s, beating C++ (code can be ported however). But yes, "I expected Go to win..." is exactly the core of the problem here. Same as with e.g. Swift, which people expect to perform on the level of Rust, when it is even slower than Go. The intuition caused by common misconceptions just does not correspond to reality sadly.
- pjmlp 3y agoIt only goes to show how much cargo cult is there in adopting these languages in hipster circles.
- hnlmorg 3y agoNo. What it actually demonstrates is that people didn’t read the source material properly. The Java and Go versions use different optimisations. There’s nothing stopping either language from using the same optimisations as the other. It just wasn’t something their respective authors cared to try in their respective exercises.
- deleted 3y ago[deleted]
- neonsunset 3y agoThere, however, is something stopping Go from using optimizations present in Java or C#/C++/Rust. This is lack of SIMD API without dropping to hand writing ASM and overall much weaker compiler. This puts much greater burden on the programmer to match the performance while staying with Go.
- hnlmorg 3y ago> There, however, is something stopping Go from using optimizations present in Java or C#/C++/Rust ... > This puts much greater burden on the programmer to match the performance while staying with Go. Your second statement contradicts your first. You're not stopped from using SIMD in Go. There are in fact several 3rd party libraries out there to use SIMD. It's just not part of the standard library. So you can still use SIMD in Go without writing Go's dialect of assembly. It's also worth noting that SIMD isn't even due to drop into std in C++ until C++26. At the moment you either have to use experimental or a 3rd party library. You're also missing the point of these examples. Nobody writing these exercises are trying to claim that all languages are equal. And they certainly not trying to write idiomatic code either. They're just fun little exercises demonstrating the degree of optimisations one can go through. You wouldn't want to write code like those in the examples in all but a the tiniest of scenarios. It's silly the amount of people over-analysing this, what is essentially just a game, and then arguing its "proof" about their biases towards different programming languages.
- threeseed 3y agoJVM has always been on par if not often faster than hand-written C code. Go's advantage has always been that it is good enough at a lot of things.
- Mawr 3y agoPlease, you've been reading too much PR from the Java side and not looking at benchmarks and real-world performance enough. What you're claiming is inherently not possible, cherry-picked benchmarks notwithstanding.
- vanviegen 3y agoSure it's possible. The JVM can do guided optimizations at run time. There is no such thing for native executables.
- pjmlp 3y agoAnd as I mentioned in another comment, you can even cache PGO data between executions, not needed to start always from zero.
- threeseed 3y agoCan you explain why it's not technically possible. JVM has had decades of experience at optimally translating bytecode to machine code and can take advantage of SIMD, AVX etc when needed. Most hand-written C code is far from optimal.
- 10000truths 3y agoC compilers also have decades of experience optimally translating C code into machine code, and they are arguably more capable of emitting SIMD (good luck trying to use cutting edge AVX-512 intrinsics like vpopcntdq with the JVM). The fact is that there is nothing a JIT compiler can do that an AOT compiler can't do, but in the case of AOT, the resources spent compiling the code are amortized to effectively 0, whereas that resource cost is borne upon every program startup for a JIT engine.
- threatofrain 3y agoI don't think Go has ever demonstrated that it deserved to be thought of as casually faster than Java.
- Comma2976 3y agohttps://github.com/attractivechaos/plb2/blob/master/README.md https://github.com/attractivechaos/plb2/blob/master/README.m... Synthetic benchmarks aside, I think as far as average (spring boots of the world) code goes, Go beats Java almost every time, often in less lines than the usual pom.xml
- iraqmtpizza 3y ago[flagged]
- Comma2976 3y agoAnd yet, people will refer to some other synthetic benchmark when arguing that the average Java project, which doesn't disable GC nor uses unsafe reads et al, is comparable. Can't have and eat it too
- iraqmtpizza 3y agoUm, GraalVM (JIT) has both GC and memory safety. It's a drop-in replacement for HotSpot. It takes literally five seconds to change JAVA_HOME and you're done. The benchmark literally uses Graal, something from Java, for Ruby and Python, but inexplicably doesn't use it for Java itself.
- kaba0 3y agoSo you are comparing a feature-packed enterprise framework with a raw http server ping-ponging hello world? Also, what even does the last line mean? Go in general is significantly more verbose than Java.
- deleted 3y ago[deleted]
- Mawr 3y agoThat's only a valid comparison if the "fastest Java" and "fastest Go" implementations are either the same or at the limit of what each language allows. The more interesting comparison anyway is performance of the straightforward, idiomatic code, since that's what we all write 99% of the time. Here's the key insight from the article: "Processing the input file in parallel provides a huge win over r1, taking the time from 1 minute 45 seconds to 24.3 seconds. For comparison, the previous “optimised non-parallel” version, solution 7, took 25.8 seconds. So for this case, parallelisation is a bit faster than optimisation – and quite a bit simpler."
- tutfbhuf 3y agoYour expectation is correct. The Java version is more tuned. Here https://github.com/dhartunian/1brcgo/?tab=readme-ov-file#leaderboard https://github.com/dhartunian/1brcgo/?tab=readme-ov-file#lea..., you can find a version that runs in 1.108 and is almost 3x better than the one you quoted. I think one can reduce it even further. In the end, it depends on how fast the executable can boot up and execute the code. At some point, JVM will lose because it takes quite some time just to initialize the JVM, whereas Go executables can boot up very fast. Here you can see a comparison of Hello World Programs: https://github.com/qznc/hello-benchmark?tab=readme-ov-file#hello-benchmark https://github.com/qznc/hello-benchmark?tab=readme-ov-file#h.... JVM takes a whopping 596 ms to boot up and print Hello World, whereas Go just requires 149 ms.
- benhoyt 3y agoI think that's true with the JVM, but the fastest Java solutions are using GraalVM and its ahead-of-time compilation mode to avoid startup time. In addition, while "go run" might take 149ms to compile and run a program, a compiled Go program starts in just a couple of milliseconds: $ time ./t Hello, world real 0m0.003s
- tutfbhuf 3y agoThank you for the insights. I would like to add that native compilation with GraalVM sounds excellent in theory, but in all the real-world Java codebases that I have tested for native compilation, it wasn't possible due to some limitations in the code or some dependency (it is not a drop-in replacement).
- geodel 3y agoJava version is written by lead researcher and founder of GraalVM at Oracle labs. It is really native AOT compiled code comparable to best in C++/Rust. It is Java entry because language used is Java but finally compiled artifact is far far away from typical compiled Java artifact.
- bufferoverflow 3y ago3x difference is not "close".