5 ms·
Go is extremely performant. But then again, isn't the author comparing apples to oranges so to speak? A Go program runs as a native binary, whereas Erlang and S
by travjones 11y ago
Go is extremely performant. But then again, isn't the author comparing apples to oranges so to speak? A Go program runs as a native binary, whereas Erlang and Scala/Akka run via their respective VMs. Wouldn't these results be expected?
- dozzie 11y agoYou mean, he should implement a VM for Go or in Go? So the comparison is fair, but totally useless by ignoring the way programs in those languages are typically run? It wasn't meant to be fair, it was meant to be relevant. Of course the results are more or less expected. JVM is by far the worst, because it uses OS-level threads, while Go and Erlang use userland threads, which are way cheaper to spawn and manage. [edit] According to some other comment around here, Scala is supposed to use userland threads as well.
- travjones 11y agoNope. I just think the comparison should be nuanced. I agree that these data are relevant. Yup.
- emergentcypher 11y agoScala runs on JVM and uses OS-level threads. However, Actors are not threads, so in a way it's like user threads. One million actors will be scheduled to run on a pool of OS threads.
- memset 11y agoThe author also measures .net core, which has the best performance of them all. I believe that is also running non native. Moreover, the core assumption that native == faster is not true. One advantage of the jvm is that as a program runs, the runtime can internally profile and adjust the byte code on the fly in order to increase performance.
- travjones 11y agoHey! Yeah, I just noticed the author added .Net core (this wasn't apart of the benchmarks when it was first posted to HN). I agree that the assumption is violated. On the topic of native code though, check out the numbers for .Net core on Win 8.1 vs. Mac OS X (almost 3x faster on Windows, which is expected).
- wizzard0 11y ago(dotnetcore version author here) Please note that Windows and OS X is benchmarked on different CPUs! You're welcome to re-test at dual-boot MacBook together so we can meaningfully compare OS X/Windows
- deleted 11y ago[deleted]
- radicalbyte 11y agoIf anything is unfair it's that they're using long ints. Java (and I assume other JVM languages) have the overhead of allocation for most of the longs. Testing with allocation in all languages will give a better idea of performance (and I won't be surprised if .Net core fares very well).
- dtech 11y agoJVM has primitives for longs
- benashford 11y agoIs the .NET version actually spawning any threads at all? It uses Tasks to collect the results, but all the work is done in the main thread by the looks of it.
- wizzard0 11y ago.NET version has 2 variants for exactly this reason :) Single-thread version is fastest of course.
- mdasen 11y agoWhat you're saying could be taken two ways. 1. That the time (including start-up time) for something on the JVM would be longer because the JVM needs to start up. 2. That Go producing a native binary is automatically faster at things. In reference to the first, the benchmark timings are started when the software actually starts running. In terms of the second, being a native binary doesn't mean faster. Go still has a runtime. It's just included in the binary. Go's performance advantage is probably a few things. Go was made to spawn millions of goroutines and Go uses primitive types. I don't know all that much about Scala, but I believe it doesn't do primitive types which means that every one of those Int objects requires following a pointer to get to the value. That's overhead. EDIT: this looks like it's wrong as Scala has a bunch of pre-defined classes that extend AnyVal and correspond to primitive types in Java. It also looks like the Scala code is passing back a Long even when the value is still small enough to fit in an Int. That's doubling the amount of memory when that memory only needs 64-bits near the end stages. By contrast, the Go code does `sum := 0` which I'm not actually sure how that's working. If I initialize a 32 bit int without specifying it, I see that I wrap around (http://play.golang.org/p/PiiMZmEzKp http://play.golang.org/p/PiiMZmEzKp). So, I'm not sure how initialising it to 0 and then adding to something over an int32 works. Maybe Go uses a different default int depending on platform? Go's implementation is also simpler. In the Scala version, there's a receive method and the sub-actors just pass back when they're done potentially causing a bunch of switching. Go, on the other hand, creates all the goroutines and only when that's done starts receiving from them. In the Scala version, the program might think that there's value in switching from creating the sub-actors to receiving from them - and they should pass back very quickly. The implementation here in Go doesn't allow for that switching. When dealing with something as synthetic as this, all of these little things matter.
- srean 11y agoIt would still be fair as long as they are equally idiomatic in their respective languages. If one solution avoids slow startups,requires less of programmer's 'think cycles', the need to wait twiddling thumbs while something compiles or warms up; then there is still a legit point to be made. Not a fan of Go by any means but have to give it credit for making concurrency more mainstream
- pcwalton 11y ago> A Go program runs as a native binary, whereas Erlang and Scala/Akka run via their respective VMs. Wouldn't these results be expected? No? Erlang and Scala both have JITs. The JVM does quite a bit more optimization than Go's compilers do.
- im_down_w_otp 11y agoErlang doesn't have a JIT. BEAMJIT hasn't been released yet.