26 ms·
Rust is now overall faster than C in benchmarks
- ma2rten 6y agoI'm having a hard time making sense of this page. Why is this comparing fastest implementation with slowest implementation? Why is the metric busy time/least busy? Why is C++ so much better than C?
- jeffbee 6y agoSpeaking generally and about no specific program, you should expect C++ to be faster than C. C++ has more ways for the programmer to communicate with the compiler.
- vitus 6y agoAt the same time, a lot of those mechanics involve additional overhead (e.g. vtable lookups for dynamic dispatch per inheritance). But yes, some of these do provide hints for the compiler, e.g. constexpr, ownership semantics per unique_ptr. There's nothing stopping a human from writing equivalent C, so my suspicion is that the performance gap is primarily due to the benchmark implementation.
- jeffbee 6y agoYou've got it backwards. For the same amount of polymorphism in the design of a program C++ is likely to be faster because a C++ compiler can often devirtualize calls but a C compiler faced with a home-grown vtable (the struct of function pointers that every large C program eventually uses) will never be able to do so.
- vitus 6y agoWhy bother to write the vtable in the first place? My experience is that C++ that's written for performance will often prefer the use of templates over inheritance since the cost is then paid upfront by the compiler. What's stopping a C programmer from hand-coding template instantiations (via macro or otherwise)?
- jeffbee 6y agoSure you are welcome to reimplement C++ in C macros. When your time is worthless anything is possible.
- Skunkleton 6y ago> When your time is worthless anything is possible. I kinda want this on a mug or something.
- jandrewrogers 6y agoWhile nothing prevents you from writing C that will generate the equivalent code, it requires several times more lines of C than the equivalent C++. At which point, it becomes an economics discussion. C is usually a choice when pure performance is secondary to other considerations like portability. Most C++ code I see has few vtables, and what vtables exist are mostly removed by the compiler. Java-style inheritance hierarchies are not idiomatic in C++. The code gen for C++ looks a lot like hyper-optimized C code, but without having to write hyper-optimized code. C++ naturally provides much more information about intent to the compiler than C does, and modern compilers are excellent at using that information to provide nearly optimal code gen.
- pjmlp 6y agoJust a small, correction, you mean 90's style C++ GUI frameworks inheritance are no longer idiomatic in modern C++. Naturally we have to ignore that wxWidgets, Gtkmm, MFC, ATL, Qt, COM, DirectX, IO Kit, DriverKit, Skia are still around.
- clappski 6y agoProbably fairer to say that the virtual inheritance architecture is idiomatic to GUI libraries rather than any particular language? You even mention GTKmm, a C++ wrapper around a C library that leverages inheritance.
- pjmlp 6y agoI can also pull iostreams, CORBA, COM/DCOM and more recently UWP cards if you like. Being around long enough, the meme writing Java in C++ just rubs me the wrong way for something that was already common several years before Gosling even thought of Oak. As if C++, alongside Smalltalk, and all those enterprise object modelling methodologies and books, weren't to blame for the widespread of that way of programming. When Java came into the scene, those C++ and Smalltalk developers (and enterprise architects) migrated to it, and kept doing what were already considered "best practices" by then.
- 6y ago
- deleted 6y ago[deleted]
- FartyMcFarter 6y agoLooking at the reverse-complement code, it appears that the Rust and C implementations are using different algorithms: https://benchmarksgame-team.pages.debian.net/benchmarksgame/program/revcomp-rust-1.html https://benchmarksgame-team.pages.debian.net/benchmarksgame/... https://benchmarksgame-team.pages.debian.net/benchmarksgame/program/revcomp-gcc-6.html https://benchmarksgame-team.pages.debian.net/benchmarksgame/... On a quick inspection: - The Rust code is about twice as long. - The Rust code has CPU feature detection and SSE intrinsics, while the C code is more idiomatic. - The lookup table is larger in the Rust code.
- vitus 6y agoI recall an anecdote about how Haskell actually outperformed C on various tree benchmarks because it was using a better implementation. At some point, the C programmers got fed up with the airs of superiority from Haskell programmers, ported the Haskell implementation, and reclaimed their position. I wouldn't be surprised if there's something similar happening here.
- _wldu 6y agoYes, it seems everyone is always trying to beat C, but really, no one can.
- harporoeder 6y agoThere was a long period where a fairly unknown theorem proving language ATS (1) was beating C in many test cases on the benchmark game (2) the benchmarks were removed though (3). I expect many languages could be made to win with sufficient effort. 1. http://www.ats-lang.org/ http://www.ats-lang.org/ 2. http://web.archive.org/web/20121218042116/http://shootout.alioth.debian.org/u64/ats.php http://web.archive.org/web/20121218042116/http://shootout.al... 3. https://stackoverflow.com/questions/26958969/why-was-the-ats-language-dropped-from-the-computer-language-benchmarks-game https://stackoverflow.com/questions/26958969/why-was-the-ats...
- lmilcin 6y agoWhich is not at all surprising. Rust has much larger compilation unit and knows more about what can read/write a particular piece of memory. This allows some occasions for optimization where C compiler must be conservative. An example of simpler version of this is Fortran that can be faster for numerical loads due to the fact that Fortran disallows aliasing of function arguments. C on the other hand, must pay the price of having to be conservative with how it treats arguments just in case they overlap.
- pmarin 6y agoThe only conclusion I have got about this web site is how much some programmers like to write benchmark code in Rust.
- indymike 6y agoLet's talk about speed when we are implementing the same algorithm and optimizations, please. If $1 was donated to cure cancer every time a developer games a comparison like this, there would be no more cancer.
- burnthrow 6y agoI sort of doubt that, billions of dollars have been spent on cancer research.
- mh7 6y agoSome of the rust versions calls C libraries for its heavy lifting (gmp, pcre) so I wouldn't take this too seriously.
- sitkack 6y agoAs soon as the libraries are RiiR, then the Rust compiler can optimize across those library calls.
- burntsushi 6y agoThat's not good enough. Rust already has a pure-Rust regex library. (I'm its author.) It is the only non-PCRE regex engine to appear in the first 20 results of the regex-redux benchmark. (The 21st I believe is currently RE2.) When using the regex crate, you would not materially benefit from optimizations across library calls, nor is it the difference maker here. Highly optimized regex engines depend more on internal inlining. Take a look at the object code for a program compiled with PCRE2 or the regex crate. You'll find huge functions internal to the regex library where inlining has been forced to reduce overhead. Those things are never going to be inlined across library boundaries.
- sitkack 6y ago> Those things are never going to be inlined across library boundaries. What prevents this? I trust you on on this, but where is the remaining work? Language semantics, compiler, third choice?
- burntsushi 6y agoIt's prevented by good sense. The functions are likely multiple KB in size. Inlining them would seriously bloat the binary and would be unlikely to help due to how much work most regex engines do on each search. The remaining work _on this particular benchmark_ is the regex algorithm itself. I'm on mobile so I can't do a deep dive, but I haven't yet figured out how to easily improve on this particular case. It has to do with the fact that the benchmark has a high match count and the finite automata approach in the regex crate has a bit higher overhead than the typical backtracking solution used in PCRE2 (which is also JIT'd in this case). It's not the language, compiler, inlining or any other such thing. It's algorithms. But this is one single benchmark. Before regex-redux there was regex-dna, and Rust's regex crate was #1 there. Why? Same reason. Algorithms. You can't judge regex performance by a single benchmark. Two won't do it. Not even ten. It's one of the many problems with the Benchmark Game. This would be fine if everyone was circumspect and careful with their interpretation of the data provided, but they aren't. And the Benchmark Game doesn't really do much to alleviate this other than some perfunctory blurbs in some corners of the web site. With that said, running a benchmark is hard work. It's easy to criticize.
- Matthias247 6y agoApart from those benchmark games a lot of real world C is a lot less performant than people think it might be. I spent a fair amount of time reviewing C code in the last 5 years - and things that pop up in nearly every review are costly string operations. Linear counts due to the use of null terminated strings and extra allocations for substrings to attach null terminators, or just deep copies because ownership can’t be determined are far more common than exceptional. This happens because null terminated strings feel like idiomatic C to most people. Rust avoids those from the start by making slices idiomatic. Another thing I commonly see is the usage of suboptimal containers (like arrays with linear search) - just because it’s there’s no better alternative at hand (standard library doesn’t offer ones and dependency management is messy). Which also makes it less surprising that code in higher level languages might perform better.
- martincmartin 6y agoAlso lack of generics can make it slow, e.g. qsort() requires a function call for each comparison. So C++'s std::sort() can be significantly faster on an array of integers.
- mh7 6y agoIt's more to do with the fact that std::sort's definition is visible to the compiler and qsort() is not. Put qsort() code in stdlib.h, make it static and write a static intcmp() and you'll see the compiler inline that no problem.
- ryanianian 6y agoSure you can hard-code intcmp into qsort but then it would only work for arrays of ints. You could do some macro magic instead of templates e.g. `DEFINE_QSORT(int, intcmp)` which could stamp out `qsort_int` but that's not a part of the stdlib. C++ arguably gets this right since sort<int> and sort<string> will be separate functions, although templates are of course a footgun. And of course duping the logic for std::sort<T> for a bunch of different T impls increases the binary size.
- Animats 6y agoTwo charts with different languages. Unclear what is being measured. Is this a humor article?
- nindalf 6y agoThis site has a page where they explain what they're doing - https://benchmarksgame-team.pages.debian.net/benchmarksgame/why-measure-toy-benchmark-programs.html https://benchmarksgame-team.pages.debian.net/benchmarksgame/... Basically, it's toy programs written in each of these languages. They measure how fast each one is executed. This methodology does have it's limitations, which that page is upfront about.
- notorandit 6y agoI am not sure I can buy such a comparison. Someone smarter than me already argued about test implementations. Someone else also put compilers and interpreters into prospective. Of course language expressiveness can gauge in but, IMHO, comparing the same sort algorithm or the same hash table implementation (or n-queens algo) could make much more sense especially with comparable compilers. If Rust implementation is father than C's, kudos goes to the compiler, not to the language
- dodobirdlord 6y agoThe Rust language specifically gives more information and thus more optimization opportunities to the compiler. Plus, when comparing Rust code compiled with rustc and C code compiled with Clang, both are using LLVM as the compiler backend, so what primarily comes into play is how expressive each language is, and how idiomatic it is to write code that will be optimized by the compiler. Both C and Rust are capable of just inlining optimal assembly, so comparing "pure speed potential" is pointless.
- notorandit 6y agoOK. So you say that implementations are the same within the respective language capabilities and that the Rust compiler frontend is inherently better than C's thanks to the language expressiveness? Still sounds weird to me, unless the test programs use very different approaches, like parallel programming...
- rurban 6y agoBecause Rust does alloca for all locals, and this if course faster. Everyone else avoids it for security reasons. Just search the Rust bugtracker for stack overflows.
- steveklabnik 6y agoYou are confusing the llvm instruction “alloca” with the C feature “alloca.” llvm will use its alloca instruction for C and C++ local variables the same way as Rust does. You are correct that the C feature is often banned. Rust doesn’t even support it at all.
- rurban 6y agoNo, you are still confusing it. llvm alloca reserves a stack allocation slot. The number of slots is unchecked that's why rust has so many stack overflows. Esp with varargs. Check your issue tracker or source code.
- steveklabnik 6y agoRust doesn't support varargs. It also supports stack probes on x86, guard pages, all that stuff. It is runtime checked because it is not possible to compile-time check.
- tpoacher 6y agoAh, rust. A language which combines the flexibility of assembly language with the power of assembly language.
- tpoacher 6y agoDefine 'c'.
- tutfbhuf 6y agoNodejs is incredible fast for a interpreted language. It is only ~4 times slower than Rust and only a bit slower than Go or Java (compiled GC languages) in the benchmarks. Compare that with Python 3, also interpreted but ~30 times slower than Rust. I know that Python 3 can do some runtime stuff that Nodejs can't, but I wonder whether that's worth so much performance. Maybe if the answer is that you would include C modules in Python if you need the speed, but I don't know if that's a good answer to the problem.
- brundolf 6y agoNode uses V8, which does JIT compilation, while CPython is a straight bytecode interpreter. A better point of comparison would be PyPy
- tutfbhuf 6y agoAre there any CPython vs PyPy benchmarks?
- igouy 6y agohttps://pybenchmarks.org/ https://pybenchmarks.org/
- tutfbhuf 6y agoOkay according to their results: https://pybenchmarks.org/u64q/chartbox.php?s=eNptUtttAzEMW0lPUprC%2B29TGr0kQNP7IU42RYpy2%2F1Ov4DMPR0s6K8yB6exgz60cBXhhO2H8EB7uXhmLkIK53TXFA%2FVq%2FPAyvOb90Bir94m%2BzR3pg4XCxykucUXQVZ006tHQpjYkULYyCd7vD%2B8cJ83RBlTQp4tL7AcNRvaSm9s4%2FIiwv%2FqOafEy6pUTwJ59dbD7nzXLoJzzf%2FhTfTl7a7ORnHGTbAUK4m8ef47X27Hr8GUF4bdLsvsOhMa7%2BqlVUlBYfENqww0QzhDQmhlr8UZTTxkQq694F96KxcrHmL3MG0gwLZSUp7brmmfmxFZL1CzCe22plOrUlFPg8Hknk1n4%2F1eQvv3F2BTYciZmgsKMJcQVT7jiInnvfwA36GR7A%3D%3D&m=eNozMFZwSU1WMDIwMlAoNTMpBAAfLQPk&w=eNpLrizJyM%2FzL6gsLgFTBZVgwhhIgiSM%2FfNKM0uyE6Fc3ZTUMijTP70oMTHHPzczuSgfKpIFoYpKi0sgIgACryZf https://pybenchmarks.org/u64q/chartbox.php?s=eNptUtttAzEMW0l... PyPy seems to be twice as fast as CPython in these benchmarks. While this is indeed a noticeable achievement, it is still much slower than Node.
- topspin 6y agoIs it just me or has that 'benchmarks game' site been growing less navigable over time? It use to be easy to compare benchmarks across several languages. If that capability still exists somewhere it's buried and I'm not interested in puzzling it out. There are no side bars or menus or anything helpful.
- fancyfish 6y agoIt's a bit hard to find, but the page comparing languages is found via the main page -> "Which are fastest?" https://benchmarksgame-team.pages.debian.net/benchmarksgame/which-programs-are-fastest.html https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
- igouy 6y ago1) The parent post linked to charts which "compare benchmarks across several languages". 2) The home page (click the banner) has links which compare benchmarks across two language implementations. 3) Each of those comparison pages has links which compare all the programs, for all the language implementations, for each benchmark.
- etaioinshrdlu 6y agoI know it's a meme, but it really does seem like most C or C++ code would be better off transitioning to Rust at some point. That includes the entire Linux kernel, web browsers, entire OS's...
- acje 6y agoIt struck me a while ago that the most powerful feature of rust is the strong contracts libraries can and must express. This allows people with much deeper knowledge than me to make awesome stuff I can depend on.
- dilap 6y agoMy experience using ripgrep and fd is that this is also true in real-world programs. :-)
- infoseek12 6y agoAn unrelated rant about benchmarksgame. Has anyone noticed that the Python implementation of regex beats a lot of the Rust and C implementations? That’s because it uses the PCRE2 library (written in C) which it assumes is installed on the OS. Benchmarks are always artificial but this seems like a step too far: the benchmark hardly says anything about Python and is dependent on the OS environment having the right dependences. https://benchmarksgame-team.pages.debian.net/benchmarksgame/program/regexredux-python3-2.html https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
- nhumrich 6y agoSure, I understand your concern. However, this is also very representative of python. Python programs are very much about using libraries for the heavy lifting. Python has never been a "distributable single binary" language, and has always required certain OS dependencies, or installable "wheels" (binary dependencies)
- JZerf 6y agoI wrote that program in the hope that it would better illustrate why some of the benchmarks on the site aren't very good since for some benchmarks the program performance is highly dependent on the libraries being used and not the programming language implementation itself. I know at least one person opened an issue regarding this on the site issue tracker at https://salsa.debian.org/benchmarksgame-team/benchmarksgame/-/issues/317 https://salsa.debian.org/benchmarksgame-team/benchmarksgame/... and I also believe I recall one of the Rust regex crate developers mentioning this too. I know that using PCRE2 in a Python program isn't typical but the Benchmarks Game does allow using other libraries and many of the previously submitted programs have been doing this for a long time already. The pidigits benchmark is the other benchmark that is heavily dependent on the libraries being used as is illustrated by their being a nearly ten way tie for second place by a bunch of programs that all use GMP.
- infoseek12 6y agoIt is an excellent illustration of that issue! And a needful reminder, as long as the implementations being compared are allowed use of that strategy. It would be interesting to see benchmark comparisons with somewhat more rigorous guidelines about what’s being compared, perhaps mandating the use of the same algorithm. That approach would introduce problems as well, like some languages benefiting more than others from the chosen algorithms. I think benchmarks are useful but the fact that they’re so often “flawed” or “misleading” may paradoxically mean that we need more of them so we can get a clearer view of the field.
- savant_penguin 6y agoWondering around the site I found this particular benchmark interesting https://benchmarksgame-team.pages.debian.net/benchmarksgame/performance/nbody.html https://benchmarksgame-team.pages.debian.net/benchmarksgame/... Why is julia using 250x the memory? (and it`s still fast)
- stabbles 6y agoIt's including compilation time and memory too, which I would consider a major flaw in the benchmarks game. If I wrap things in a function and run it a second time in the repl, this is what I get: $ JULIA_LLVM_ARGS="-unroll-threshold=500" ~/julia-b00e9f0bac/bin/julia -O3 --check-bounds=no julia> include("nbody.jl") run (generic function with 1 method) julia> @time run(50000000) -0.169075164 -0.169059907 2.044478 seconds (294.25 k allocations: 12.599 MiB, 8.89% compilation time) julia> @time run(50000000) -0.169075164 -0.169059907 1.867936 seconds (12 allocations: 1.750 KiB) So, the second time there's no compilation overhead, just like in Rust, C, C++.
- ChrisRackauckas 6y agoJulia is not allowed to use its compiler (PackageCompiler.jl) but Rust and C are. It's really silly and imposed by the author of the benchmarks for no clear reason.
- batmansmk 6y agoWas the Formula One pilot Schumacher as good as he is just because of his Ferrari? Obviously not, but he probably wouldn't have performed as well with a Ford Focus. If you are willing to spend the time to perform at the highest level, Rust can bring you there.
- eeZah7Ux 6y agoThanks, I'd rather not use it. My time is valuable as well.
- olodus 6y agoYeah I can understand why. Though I still prefer C in some ways simply because of its minimalism in the language, while still allowing for the kinds of things you want to be able to do if you wanna push your code to the limits. It is a bit scary sometimes writing in C though and sometimes I get a bit annoyed at how some things work or not work in it. I personally am hoping Zig can soon fill this minimalism trait in langs for me. C will probably always be the standard though and I do think more programmers should learn C better to become better programmers. Rust is a good lang though. I am glad something else is pushing up there for the top spots. And more competition in performance is a good thing. You don't always have to pick your sides. I just want to be able to write good code and be happy writing it :)
- dnautics 6y agoYou'll be happy to know I implemented the n-body benchmarks game in zig 0.6.0 and it absolutely thrashed the rust version. Submitted it, but they don't take PLs not on the board currently.
- adamnemecek 6y agoBut how much? Do you have an idea why?
- dnautics 6y agoHonestly I have no idea. You can try it yourself, or put it through godbolt: https://gist.github.com/ityonemo/f34e0d3b4891f481863980a31426f1ca https://gist.github.com/ityonemo/f34e0d3b4891f481863980a3142... Note it could also be platform dependent. I'll give it a whirl on my own (new) machine.
- huhnmonster 6y agoDo you think that it may be caused by use of comptime? I have not looked at the benchmark implementations, but that kind of struck me as a reason
- helloycombinat 6y agoMisleading title. C++ is still faster
- anta40 6y agoThere are 2 charts on the page, both using the same title: "How many times slower?" I don't get those. What's the difference?
- igouy 6y agoThe different charts show different programming language implementations.
- JoeAltmaier 6y agoApples and oranges. How about Rust vs C++?
- haxorito 6y agoIt’s all depends on developer. I have talent to write really bad code in any language and make code as slow as I want. I can write code in ruby that would outperform code in C. The benchmarks like this don’t give you full picture of language possibilities. On top of everything we also need account for compilers and compiler optimization. Nothing against rust. I write ton of code using rust, and advocating at my work. But this looks like a PR move to me.
- sriku 6y ago... but not as fast as C++/g++ ?
- timbit42 6y agoYet...
- hvasilev 6y agoHow do I downvote a thread in HN, I can just upvote it? Also is there also a way to filter out posts with the word "Rust" in it so I don't see them?
- ksec 6y agoThe only option is to Hide it.
- wuxb 6y agoJust took a quick peek at the binary-trees C code. Why using openmp while the others don't? why use recursive functions? The C implementation is not correctly optimized. People just paid more attention to Rust and other languages. Rust can be as fast as C, but "faster" is really misleading. BTW, I use clang all the time since it's better than GCC.
- Tade0 6y agoIt seems that someone simply tacked openmp on without checking if it actually increases performance in this case - which is unusual, because I remember a course in college, part of which was a project aiming to teach the student that openmp is not a silver bullet and should be used only when it actually helps.
- igouy 6y agoHow do you know that this is not one of those cases when openmp actually helps?
- JZerf 6y agoI submitted the C binary-trees program. I did check to see if OpenMP increased the performance and it most certainly does. Just looking at the CPU and clock time usage on https://benchmarksgame-team.pages.debian.net/benchmarksgame/performance/binarytrees.html https://benchmarksgame-team.pages.debian.net/benchmarksgame/... you can see that the clock time used is about one third of the CPU time that was used.
- JZerf 6y agoYou're probably referring to the C program I submitted. OpenMP is only available for C, C++, and Fortran so that is why most programs won't use it. However most of the other programming languages have their own ways for doing multi-threading and many of the programs for this benchmark do make use of them. The rules at https://benchmarksgame-team.pages.debian.net/benchmarksgame/description/binarytrees.html#binarytrees https://benchmarksgame-team.pages.debian.net/benchmarksgame/... request that submitters use the same algorithms as existing programs and I try to follow that rule. I believe all the binary-trees programs are using recursive functions so naturally I did the same to avoid breaking the rule about using different algorithms.
- layoutIfNeeded 6y agoC++ still seems to be the fastest.
- harporoeder 6y agoI was wondering if perhaps this was actually measuring a difference between LLVM and GCC, but they also provide a set of benchmarks of C Clang vs C GCC (1) and Clang is generally slower in those test. Although there is some correlation between the ones Clang wins in C And Rust. 1. https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/c.html https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
- indolering 6y agoThe Rust vs C Clang comparison [1] has Rust winning on every benchmark except pidigits, and that's only by .01 seconds. Memory usage and binary size is competitive as well. [1]: https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/rust-clang.html https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
- arcticbull 6y agoRust can be faster than C because in general C compilers have to assume that pointers to memory locations can overlap (unless you mark them __restrict). Rust forbids aliasing pointers. This opens up a whole world of optimizations in the Rust compiler. Broadly speaking this is why Rust can genuinely be faster than C. Same is true in FORTRAN, for what it's worth.
- alerighi 6y agoWell you are saying that even in C you can use the restrict keyword to tell the compiler that 2 memory locations can overlap. Of course is in the hand of the programmer to tell the compiler to do so. I don't think there is a fair comparison between Rust and C: C is just an higher level assembler, if the programmer knows what he's doing he can use the hardware 100% of its potential. That is the reason why C is still used in all the embedded applications where you have ridiculous low power microcontrollers and you must squeeze out the best performance. That is the difference between C and Rust to me: for each fast Rust program you are guaranteed that you can write an equivalent performant program in C (or assembly). Worst case scenario you use inline assembly in C and you get that. Thus the contrary cannot be true for Rust: if I give you a heavily optimized C program not always you can produce an equivalent version in Rust. Also not always these optimizations are what you want. In C you can choose the level of optimizations, and most of the time, at least on the program that I write, I choose a low level of optimization. The reason is that a lot of time performance is not the only thing that matters, but it maybe matters most the stability of the code (and a code compiler with optimizations is more likely to contain bugs) or the ability to debug (and thus the readability of the assembly output of the compiler). Rust gives out an horrible assembly code, that is impossible to debug, or to check for correctness. You just have to hope that the compiler doesn't contains bugs. For the same reason Rust is the ideal language to write viruses, since it's difficult to reverse engineer.
- albertzeyer 6y agoInterestingly, C++ seems to be the fastest overall.
- agumonkey 6y agoAfter the rust blossom storm I didn't track cpp implementation evolutions.. did cpp compiler perf/libs increased or was is simply faster and still is the same ?
- burnthrow 6y agoWas faster and is the same, checking isn't free. Not that Rust is slow. C++ is unsafe by default whereas in Rust it is opt-in (lexically scoped). The Rust implementations don't appear to use `unsafe`.
- steveklabnik 6y agoChecking can often be free, because it’s done at compile time, rather than at runtime.
- kowlo 6y agoSearched the page for "Rust" which returned nothing... and the box labels are awkward. Why not label them conventionally?
- kzrdude 6y agoRust seems to be using parallelism better. In one benchmark though (fasta), C gcc is using all 4 cpus and Rust only two, and still wins. (Looking at just C gcc vs Rust) https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/gcc-rust.html https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
- FartyMcFarter 6y agoThe C version uses OpenMP, while the Rust version doesn't. I tried running the C code with 2 and 4 threads, wall-time and CPU time don't change much in either case which is strange (this is cygwin with gcc 10.2.0): 2 threads: $ /usr/bin/gcc -pipe -Wall -O3 -fomit-frame-pointer -march=ivybridge -fopenmp fasta.c -o fasta.gcc-2.gcc_run && time ./fasta.gcc-2.gcc_run 25000000 | md5sum fd55b9e8011c781131046b6dd87511e1 *- real 0m0.724s user 0m1.468s sys 0m0.108s 4 threads: $ /usr/bin/gcc -pipe -Wall -O3 -fomit-frame-pointer -march=ivybridge -fopenmp fasta.c -o fasta.gcc-2.gcc_run && time ./fasta.gcc-2.gcc_run 25000000 | md5sum fd55b9e8011c781131046b6dd87511e1 *- real 0m0.670s user 0m1.514s sys 0m0.046s
- moldavi 6y agoShouldnt they be about the same? (At least until the LLVM immutability optimizations happen) I suspect surprising factors are in play.
- jug 6y agoI'd look at the algorithms here. Looking a bit fishy with sometimes quite serious differences...
- skohan 6y agoThe ceilings should be similar, but there is an argument that there are cases where idiomatic Rust might outperform idiomatic C or vice versa. For instance, in real-world usage, you might do a bit more redundant copying in C in places you would avoid it with the borrow checker in Rust. Conversely, enforcing RAII in Rust might cost performance in some scenarios relative to C.
- yudlejoza 6y agoWhen Rust is faster than C in a benchmark in which C++ is also faster than C, I know I can safely ignore such benchmark.
- tetromino_ 6y agoThe problem is not with C the language, but with the C standard library, which has many inefficiency warts. Examples: * Strings. Any form of string access other than scanning the string's characters one by one from start to finish can benefit from knowing the string's length in advance. In C++, std::string and std::string_view know their lengths; plain C strings don't. Thus, in performance-optimal plain C, almost any function that takes a string parameter ought to also take the string length as a separate parameter - but most C standard library functions neglect to do so. * Callbacks. When the callback is static, you want to give the compiler the opportunity to inline it into the call site. In C++, this is natural: pass the callback as a template parameter. In performance-optimal C, you'd want to provide macro version of functions that take callbacks. But the C standard library only supports callbacks as function pointers (e.g. in bsearch(3), qsort(3) etc.), which means unnecessary pointer dereferences and which makes inlining impossible.
- gambiting 6y ago>>plain C strings But.....there is no such thing. There are arrays of chars, the whole principle of C is "if you want to know the length of a string....just store it yourself". It's a bit like saying that two wooden planks don't have the same functionality as a cupboard. Like, you're technically correct, but the whole idea is that you can use the planks to build your own cupboard or literally anything else.
- jolux 6y agoThe comment was illustrating why not including the length is a problem: it lead to a community norm that is bad for performance (stdlib functions not taking string length).
- lambda 6y ago
- nynx 6y agoThe fastest n-body program is written in very idiomatic rust. https://benchmarksgame-team.pages.debian.net/benchmarksgame/program/nbody-rust-8.html https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
- FartyMcFarter 6y agon-body in C compiled by clang runs just as fast as Rust apparently: https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/c.html https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
- pjscott 6y agoIt's not entirely surprising that a carefully-optimized C program using explicit SSE intrinsics, plus a fancy trick involving a low-precision square root instruction fixed up with two iterations of Newton's method, would be fast. :-) What impresses me is that the Rust version didn't do any of that stuff, just wrote very boring, straightforward code -- and got the same speed anyway. Some impressive compilation there!
- FartyMcFarter 6y agoGood point! It would be interesting to find out where the Rust version gets most of its speed from.
- amelius 6y agoYes, it could be mostly LLVM doing the heavy lifting here, for all we know.
- neopallium 6y agoThe Rust compiler can auto-vectorize loop code. This blog post shows how to write simple idiomatic Rust code that will allow the compiler to auto-vectorize: http://cliffle.com/p/dangerust/6/ http://cliffle.com/p/dangerust/6/
- api 6y agoOne of Rust's performance advantages is the compiler's ability to unambiguously determine memory aliasing. Aliasing is why many numeric kernels are written in Fortran, a much older language that also enforces strict aliasing as it simply doesn't allow overlapping references. There are probably others as well, but this is the advantage I'm familiar with. C's ambiguity makes it harder to achieve some optimizations that can really matter on modern CPUs.
- nynx 6y agoLLVM's support for this is bugged, so rust does not currently take (edit: full) advantage of it.
- kzrdude 6y agoDoes not fully take advantage of it.
- steveklabnik 6y agoRust does not take full advantage of it; that is, &T will still get noalias, it's &mut T that's currently disabled. The tracking bug is https://github.com/rust-lang/rust/issues/54878 https://github.com/rust-lang/rust/issues/54878
- lambda 6y agoHere is an example which, while trivial, demonstrates some of the optimization issues you can run into in C and C++ but not in Rust, even with noalias currently only applying to &T. C++: https://godbolt.org/z/dTPsbh https://godbolt.org/z/dTPsbh Rust: https://rust.godbolt.org/z/Mdx87h https://rust.godbolt.org/z/Mdx87h In C and C++, compilers are allowed to infer "noalias" based on pointer types; two pointers of different type are not allowed to alias. This is known as type-based alias analysis. But char * is given special treatment, because of its use as a generic pointer type; so if one of your arguments is char * or even signed char * , that disables any optimizations which were relying on type-based alias analysis. This provides both for performance and undefined-behavior footguns. If you ever try to use some pointer type other than char * or signed char * to refer to data of another type, you may inadvertently cause type-based alias analysis to kick in, causing invalid optimizations and miscompilation. On the other hand, if you have a function which takes both a char * and another pointer, the compiler may not apply optimizations that it otherwise could because char * is allowed to alias anything. In Rust, there is no such undefined behavior footgun. Because of the LLVM bug, noalias isn't applied to &mut pointers so there are still some cases which could be better optimized, though it sounds like there is some progress being made on the LLVM front so it should be fixed at some point, and there are already places where the compiler can do better optimizations with better safety due to the stronger semantics of &T.
- jolux 6y agoI think benchmarking C vs C++ vs Rust must only really be useful for researchers. They’re all making a similar tradeoff for performance: forcing you to consider how you use memory. Does anyone work in a field where the performance difference between these specific three platforms matters? I’m genuinely curious. Edit: also, if you could explain briefly why and what makes particular choices out of the three unsuitable, that would be awesome too.
- jandrewrogers 6y agoIt matters for real-world software development, though the reason may not be intuitive. In theory, for any particular bit of software, you can write code in any of these three languages that has nearly identical performance. In practice, the complexity of expressing equivalent performance can vary considerably depending on what you are trying to do. There are finite limits to the complexity cost developers are willing to pay for performance. Because the cost in each of these three languages is different to express some thing, sometimes there will be a threshold where in one or more of these languages most developers will choose a less optimal design. This manifests as practical performance differences in real software even though in theory they are equally expressive with enough effort. This comes with another tradeoff. Efficient expressiveness relative to software performance comes at a cost of language complexity. C is a simple language that has enough efficient expressiveness for simple software architectures. C++ is at the extreme opposite; you can do mind-boggling magic with its metaprogramming facilities that can express almost anything optimally but god help you if you are trying to learn how to do this yourself. Rust sits in the middle; much more capable than C, not as expressive as C++. This suggests the appropriate language is partly a function of the investment a developer is willing to make in learning a language and what they need to do with it. Today, I use modern C++ even though it is a very (unnecessarily) complex language and write very complex software. Once you pay the steep price of learning C++ well, you acutely feel the limitations of what other languages can't express easily when it comes to high performance software design. I used to write a lot of C. It still has critical niches but not for high-performance code in 2021, giving up far too much expressiveness. C++17/20 is incredibly powerful but few developers really learn how to wield that power, though usage of it has been growing rapidly in industry as scale and efficiency have become more important. Rust is in many ways an heir apparent to C and/or Java, for different reasons. Or at least, that is how I loosely categorize them in my head, having a moderate amount of contact with all three. They all have use cases where you probably wouldn't want to use the others.
- seeekr 6y agoFrom the page: "… a pretty solid study on the boredom of performance-oriented software engineers grouped by programming language." I find this both funny and consider it true to some degree. There's nothing like a good old friendly arms race for the benefit of all (languages and its users, in this case) involved!
- deleted 6y ago[deleted]
- deleted 6y ago[deleted]
- 1vuio0pswjnm7 6y agoThe reasons I use C versus comparable alternatives are not limited to speed. For example, the size of the compiler toolchain, the speed of compilation and the size of the resulting executables are all factors I have to consider. I do lots of work on systems with limited resources. How does Rust compare on those points versus, say, GCC. https://dev.to/aakatev/executable-size-rust-go-c-and-c-1bna https://dev.to/aakatev/executable-size-rust-go-c-and-c-1bna
- steveklabnik 6y agoI mean, you'll get drastically different numbers with all of those examples if you actually ask for options that produce small binaries. That the default flags don't try to make things small (across any of these toolchains) means this isn't really a fair comparison. The smallest "hello world" binary rustc has ever produced was 137 bytes. https://github.com/tormol/tiny-rust-executable https://github.com/tormol/tiny-rust-executable
- fmntf 6y agoIf that's possible, why should not binaries be small (without too many downsides, eg execution speed) by default?
- pjmlp 6y agoJust like C compilers, it is a matter of use case, and compiling for size has tradeoffs regarding execution speed.
- steveklabnik 6y agoBecause everything is a tradeoff. Getting the binary to be smaller means taking more compile time, because compilers have to do work to reduce the size. It is much faster to produce larger binaries. Additionally, most compilers produce something that's useful for development and debugging by default, and that means including extra stuff for that purpose.
- mlyle 6y ago
- Svetlitski 6y agoOnce LLVM fixes some bugs with `noalias`, at which point Rust will begin using it again in more circumstances [1], I'd expect to see Rust get even faster in these benchmarks, given that the Rust compiler knows much more about which pointers do/do-not alias than most other programming languages [2] and the myriad optimizations this knowledge allows. [1] https://github.com/rust-lang/rust/issues/54878#issuecomment-429578187 https://github.com/rust-lang/rust/issues/54878#issuecomment-... [2] https://doc.rust-lang.org/nomicon/aliasing.html https://doc.rust-lang.org/nomicon/aliasing.html
- stabbles 6y agoI doubt there's any performance to be gained that way, but if so, the C implementation can just use `restrict` to the same effect.
- vvanders 6y agoHave you ever used restrict in anger? I've done it when we really needed that performance for an inner loop(particle system). It can be a real bastard to keep the non-alias constraint held constant in a large, multi-person codebase and the error cases are really gnarly to chase down. Compare that to Rust which has this knowledge built in since it naturally falls out of the ownership model.
- Gibbon1 6y agoI agree with that, no aliasing in C is an ugly kludge that bitches about perfectly fine code that benefit benefit from it. And it's hard insure that it actually works in code that does. Worse the failure is completely silent.
- jart 6y agoIs there something special about the noalias keyword that it really brings out the most unprofessional pig language in developers? https://www.lysator.liu.se/c/dmr-on-noalias.html https://www.lysator.liu.se/c/dmr-on-noalias.html