6 ms·
I expect Rust to be faster than Go as a rule because of its somewhat lower level nature and cost-less "unmanaged" abstractions but I didn't expect it to be a fu
by simias 8y ago
I expect Rust to be faster than Go as a rule because of its somewhat lower level nature and cost-less "unmanaged" abstractions but I didn't expect it to be a full order of
magnitude faster than Go for some benchmarks. Are the Go snippets not properly optimized or is there something else going on?
I think pitting Go against Rust is somewhat inflammatory but if you look at the Rust vs. C++ benchmark the results are much more similar: https://benchmarksgame-team.pages.debian.net/benchmarksgame/faster/rust-gpp.html https://benchmarksgame-team.pages.debian.net/benchmarksgame/... so clearly it's not Rust doing something right, it's the Go implementation doing something wrong. Actually even Java fares (mostly) better: https://benchmarksgame-team.pages.debian.net/benchmarksgame/faster/rust-java.html https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
- oblio 8y agoThe JVM has a ton of work put into it, it wouldn't surprise me if Java is faster than Go for quite a few things.
- jon-wood 8y agoIt’s less Go doing something wrong and more just that they do different things. Go has a garbage collector which will naturally slow things down somewhat, while Rust handles memory (de)allocation at compile time.
- _ph_ 8y agoThe problem is, that some of this benchmarks rules prevent the Go solution from using the same efficient code than its competitors, so the numbers are just not valid.
- hellofunk 8y ago> Rust handles memory (de)allocation at compile time You are saying that Rust is doing its runtime memory allocation at compile time? Are you sure you don’t mean compile time management of memory? Two very different different things.
- notheguyouthink 8y agoIsn't one of those impossible? Ie, there's only one reasonable interpretation of that sentence? Not saying being explicit isn't important, just trying to understand you.
- hellofunk 8y agoYes, what poster commented is in fact impossible.
- atilaneves 8y agoI'm still puzzled by the continued belief that a tracing GC will "naturally slow things down somewhat". Why do you think that's the case?
- yoklov 8y agoYou’re forcing the program to rediscover facts about itself at runtime. This is not free. That doesn’t mean a GCed lang is always slower than a lang where memory is managed manually. It means that the theoretically optimal implementation using GC has to do more work than the theoretically optimal implementation that manages its own memory. In the case where the theoretically optimal implementation needs a GC, the unmanaged language could always implement that anyway, but that’s vanishingly rare — typically a GC gets its speedup by using pools, which are also available to unmanaged code.
- slezyr 8y ago> Rust vs. C++ benchmark the results are much more similar Not really... Try compare sources of those programs. For example spectral-norm uses OpenMP and other things that make source look really different from the one you would write in real life. Rust program looks much simpler and closer to real life code. https://benchmarksgame-team.pages.debian.net/benchmarksgame/program/spectralnorm-rust-4.html https://benchmarksgame-team.pages.debian.net/benchmarksgame/... https://benchmarksgame-team.pages.debian.net/benchmarksgame/program/spectralnorm-gpp-6.html https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
- codetrotter 8y ago> > the results are much more similar Parent is talking about performance, not source code
- v_lisivka 8y agoC/C++ are cheating by using Intel specific instructions, like _mm_cvtpd_ps. I.e. they are with hardware-specific acceleration. If standard library will be used instead, or if Rust code will be updated to use same instructions, we will see different results.
- p0nce 8y agoIf you use a LLVM compiler, _mm_cvtpd_ps just translate to LLVM IR and is not Intel specific anymore.
- giancarlostoro 8y agoThey're using g++ though, afaik that's just using GCC is it not? But good catch altogether.
- Const-me 8y agoThat instruction is SSE2. SSE2 instruction set is guaranteed to be supported on all x86-64 CPUs, be it Intel, AMD or VIA. Similarly, the intrinsics are supported by all modern C and C++ compilers for decades already. Some compilers even generate SSE code by default for code like double x = 42.0 * y, in place of older x87 floating point instructions. x87 code is slower, and has multiple numerical stability issues.
- steveklabnik 8y agoA lot of this depends on the rules. For example, rust (rightfully) cannot use nightly, and unstable features. If it could, you could use these too. Rust will have these in the next stable release[1], so we’ll see after that ships! These intrinsics aren’t part of the C or C++ languages, but compilers provide their own, so it’s sorta like a language extension. Since they don’t use the same stability model Rust compilers do, it’s legal for them to use them. This generally means that C and C++ have a bit more leeway to use less stable/standard things. I think that’s a fine rule, given how the different languages work, but it’s a good example of how tricky all of this is. [1]: https://doc.rust-lang.org/beta/core/arch/x86/fn._mm_cvtpd_ps.html https://doc.rust-lang.org/beta/core/arch/x86/fn._mm_cvtpd_ps... and https://doc.rust-lang.org/beta/core/arch/x86_64/fn._mm_cvtpd_ps.html https://doc.rust-lang.org/beta/core/arch/x86_64/fn._mm_cvtpd...
- Tuna-Fish 8y agoExplanations for the few largest offenders: 1. regex-redux Rust has it's own regexp engine, that lacks a few of the bells and whistles of PCRE, but is much faster than it. (And has no sheer perfomance cliffs where a carefully crafted target string or search expression can DOS the app.) Also, I think the rust implementation can do less copying. GO just uses PCRE. (Which is weird, isn't RE2 a google project?) 2. binary-trees The benchmark needs to build a massive binary tree. The Rust implementation allocates it's tree in a TypedArena, which is basically a bump allocator for objects that are all dropped simultaneously. It requires very minimal metadata or work per allocation. (Not zero, because it does properly call all destructors.) The GO implementation has to use the platform allocator. The results shouldn't be very surprising... 3. Manderbrot Not sure, but I think the Rust version is designed for autovectorization while the Go one is scalar. After that the Go runtimes are within 2.5x of the Rust ones.
- Jweb_Guru 8y ago> Not zero, because it does properly call all destructors. I believe that there is an optimization that allows this to be completely avoided for types with only trivial or no destructors.
- pron 8y ago> The GO implementation has to use the platform allocator. So does the Java implementation, and still it fares much (3x) better than Go.
- deleted 8y ago[deleted]
- pcwalton 8y agoBecause the Java GC has better throughput than the Go GC. The Go GC makes enormous throughput sacrifices by prioritizing latency above all else.
- burntsushi 8y agoWith respect to your comments about regex, could you please share with me where you got your information? I would love to know so that I can go bug whoever it is to correct it. > Rust has it's own regexp engine, that lacks a few of the bells and whistles of PCRE, but is much faster than it. The only true part of this is that Rust's regex engine lacks many features found in PCRE. Mostly, these features revolve around things that are either impossible or not-known/difficult to add to a linear time implementation in an efficient way. The most popular features among these are backreferences and various types of lookaround. However, it is completely unsubstantiated to say that Rust's regex engine is faster than PCRE. At best, you can say that they are competitive with each other, where one regex engine will do better than the other on various types of workloads. Many such cases are not at all related to the feature sets of regex engines, and probably more related to missed optimization opportunities. (Anyone who has implemented a regex engine knows that the size of the set of missed optimization opportunities is unbounded.) There are of course some of those cases where it comes down to pathological differences. For example, since PCRE uses a backtracking engine even when it isn't necessary (they do have a so-called "DFA" matcher, but it must be invoked explicitly), that means it is susceptible to exponential behavior when Rust's regex engine isn't. But Rust's regex engine has pathological behavior too. The only difference is that Rust's pathological behavior takes the form of large constants, where as PCREs takes the form of exponential growth in the size of the text being searched. > (And has no sheer perfomance cliffs where a carefully crafted target string or search expression can DOS the app.) Also, I think the rust implementation can do less copying. If you're talking about PCRE vs Rust's regex, then I see no reason to claim that one does more or less copying than the other. I suspect both do exactly as little as possible. Certainly, neither of them will copy the search text. > GO just uses PCRE. (Which is weird, isn't RE2 a google project?) No. Go has its own regexp engine: https://golang.org/pkg/regexp/ https://golang.org/pkg/regexp/ The benchmark showcased in the OP for Go uses PCRE, and that's presumably because Go's PCRE variant is faster than Go's native regex engine. See https://benchmarksgame-team.pages.debian.net/benchmarksgame/performance/regexredux.html https://benchmarksgame-team.pages.debian.net/benchmarksgame/... and compare `Go #2` (PCRE) with `Go` (Go implemented regex engine). Go's regex engine in the standard library is written in pure Go, and was written by the same person that wrote RE2. (I wrote Rust's regex engine, but it was heavily inspired by RE2.) Go's regex engine does not have all the same optimizations as RE2, and in particular, it suffers from some very high constant factors in many more cases than what RE2 and Rust's regex engine. While Go's regex engine doesn't exhibit pathological behavior in the form of exponential runtime in the size of the search text, it also can be handily beaten by PCRE in a number of non-pathological cases.