This was a well-crafted benchmark, but what I found especially interesting and insightful was the "apples to oranges" part: C and Rust encourage distinct approaches, different data structures. I feel it is actually more interesting than implementing the same algorithm and comparing optimizer pipelines.
I agree. Many of us like it about C that we can build intrusive data structures easily enough. The price is more complex memory management and locking protocols, but in some cases the price is too steep in actual run-time cost. The apples to oranges comparison is not telling about whether Rust produces better code than C, but it shows how Rust's design choices force themselves on the coder and yield better results in the end. When you stay away from unsafe code, Rust makes one write code that is much easier to reason about, especially in a threaded environment. Performance is nice, but the nicer thing is correctness -- being able to get good performance along with correctness, now that is really nice.
Rust and C may encourage different data structures, but a benchmark of two programs that happen to use two different data structures doesn't demonstrate this difference. To demonstrate what you claim, you'd have to perform a more holistic language analysis than we see in the article, and you'd in practice have to talk about C++ too.
How is Rust encouraging a different data structure besides providing a btree set and not an avl tree set?
The C stdlib does not come with an AVL tree. Why would one not implement a b-tree in C for this comparison? It’s not as if K&R has “Use binary, not b-trees!” on the front cover.
Agreed. Comparing compiler pipelines is a poor way to judge how your code will perform in practice, and it's even not that useful for compiler authors, where optimizations that matter in practice are not the same.
As a meta comment, I really like how active Stepha(e?)n is on internet forums. And the energy around Rust is pretty intense. I feel like in there, people are unwilling to try to embrace some of the nuance in the arguments that some people make against Rust.
A person should understand that no language(programming or otherwise) is perfect. Therefore there is some criticism of any language that is valid. Therefore some criticism should be taken seriously as there may be a real point to the criticism.
There are many posts like this, where there are comparisons of Rust to C. Realistically they are all a little biased towards Rust as Rust is a C++ replacement really. A more proper comparison would be Zig or D as a better C against C.
Just understand that a person defending C is not always an idiot, and maybe they have point. Consider the excessive memory use of any working Rust compiler. That will probably not be remedied anytime soon and is a legitimate complaint. The ideal of how something could be is not how something is. The reality is that C works pretty well most of the time, Rust works well most of the time. They both fail at some things.
I don't think I've seen anyone claiming that Rust is a perfect language without flaws. Heck I'd hold up all of the huge strides that have been made in errors, usability and constant feedback as a counter example of that.
You see a lot of people holding up Rust precisely because we've been there for the last 5/10/15/20 years. The day I don't have to write a makefile or build yet another CMakeLists.txt is the day I rejoice.
What Rust offers is another option in the native, non-GC'd language space. A space that has very few languages and even fewer yet that are shipped at scale. Rusts inclusion w/ FF means that the have to address the robustness, security, performance and usability of the language to a degree that you don't commonly see.
Having just blown 4+ hours today dealing with the linker on a mixed C/C++ project I don't really miss a lot of the baggage that comes with native development these days. Rust gives you the option of dropping down to that level while still preserving a set of sane, opinionated defaults that are pretty well thought out.
Very strongly disagree that Rust is a C++ replacement and D is a C replacement. If anything, it's the exact opposite, Rust is a C replacement and D is a C++ replacement. If you tracked communities so far, you'd see that Rust community is very sensitive on the issue of memory print, performance impact and asm implicitness of Rust. There is already a huge osdev community built around Rust, I know kernels written in Rust. Rust is the perfect language to reliably write drivers, embedded systems or system tools. I cannot think of a language semantically closer to C than Rust. Not even C++ is there. Rust is literally just C with a good type system, and that's what makes it so awesome.
Actually Rust is clearly both a C and C++ replacement, but C programmers tend to become quite fanatical and for some inexplicable reason C also has a quite decent reputation, so the Rust community is focusing their efforts on the much more controversial C++ instead of attacking the holy cow of C.
I think they've also figured out that with time C will be squeezed into smaller and smaller areas of use, as is already happening.
Writing robust code hasn't really found a space to live in the mental model of C programmers. Using C outside a kernel or existing C project today is professional negligence.
Fantastic read. Learned a few things about profiling I'm sure I'll use.
Just one tiny gripe, don't use a blue and green next to each other in graphs if avoidable. I'm not even blue green colorblind, and I found them hard to distinguish.
Thanks for looking out for us colorblind people. But, funnily enough, there is no "blue green colorblind", and to this person with red-green colorblindness, the colors in the charts are incredibly easy to distinguish. Much easier that the typical colors chosen.
This is not really a good comparison: the author acknowledges that the C and Rust programs are using different data structures, and while he tries to vary the problem a bit to explore that difference, it's still not a fairly matched comparison, and the headline leaves the reader with the incorrect impression that we're comparing similar things.
I'm not sure that comparing "Rust" and "C" performance is even meaningful. The latter is a multi-implementation language, and in most implementations, can be written in a way that gets the compiler to generate the same machine code that the Rust compiler does. (Frequently, they both just go through LLVM.)
The fact that the two benchmarks are using different data structure is one of the main points of the a article.
The author (in my opinion) argues that each data structure would be an hell to use in the other language.
when comparing languages you need to include a measure of how idiomatic your programs are.
And in this particular benchmark, they didn't choose the same compiler backend too. Namely GCC -O2 vs LLVM -O3. This has a large impact, often larger than the frontend language, when measuring programs in native languages.
This is a benchmark comparing different data structures more than different programming languages. Of course the Rust program has fewer cache misses; this is because it’s a b-tree, not an AVL tree.
It is a benchmark comparing what type of data structure are easier to use in the two languages.
Of course it is entirely subjective (the author argues for how that is due to a static vs dynamic ownership model) and there is a single data point, which is the author rewriting the code. (two is you consider when he/she swaps one of the data structure)
C++ inheritance doesn't map well to Rust's trait system for one. I think this is an ongoing issue within the `bindgen` community, but I don't know much beyond that. Suffice to say, some concepts in C++ do not map well to Rust and so FFI can be hairy in some instances.
On instance of this becoming a complication would be in the GTK+ world with the Rust bindings to GObject. There's some really good articles about their adventures in that realm you could find.
Writing an FFI for some C++ so that C code may call it takes almost as much work as doing the same for Rust. That's less true the closer your preferred dialect of C++ is to C, I suppose.
Meanwhile Rust, in this user's opinion, offers a superior toolset for modeling data and building behavior, namely: sum types and traits.
So if you're looking to extend or integrate with a C codebase, barring some exotic target platform and all else equal, I don't know why you'd opt for C++ over Rust.
Rust interfaces very well with C. When you have a large C codebase it's easy to one day just stop writing any more C, and write all new code in Rust without skipping a beat. There are successful examples of this like librsvg.
OTOH interfacing with C++ is very hard. D might be the only language that has seriously tried it, but from Rust's perspective C++ has largely overlapping, but incompatible set of features, and it's a weird dead-end.
This comparison is disingenuous. They’re using a completely different data structure and getting a slight difference in performance, and are chalking this up to language differences. Sure, it might be harder to implement at B-Tree in C than it is in Rust. But then you can just use C++? Don’t make an apples to oranges comparison.
> [They] are chalking this up to language differences
That didn't happen. The data structure difference is discussed and the possibility of the performance difference being down to this is clearly acknowledged. Also discussed is the reason for the different data structures, which is actually the most important take-away.
-O3 isn't always strictly faster than -O2. There are different tradeoffs made about memory usage and binary size which interact with CPU caches in interesting ways.
I can't speak for the author but at my work we found -O2 to give better results on our OpenGL ES rendering engine.
TL;DR: Using dtrace to analyze the performance of AVL Trees in C vs BTreeMaps&HashMaps in Rust. Spoilers: Rust wins every time, and you should rewrite your software in Rust anyway ;).
Note that the data structure is different: AVL trees vs. BTrees. The interesting part for me was that because of modern cache hierarchies, BTrees appear to be superior than AVL trees even for in-memory data structures, while before I'd thought of them as a special-purpose on-disk data structure for databases.
It also insist on how this data is unfair and only relevant to the system (comprehensive of OS, compilers, programmer skill/talent/interest/errors and so on)
At the end the author never states that one is faster (yes, the title is misleading, but it is then clearly clarified in the text) the main part is the discussion about intrusive data structures.
[+] [-] vnorilo|7 years ago|reply
[+] [-] cryptonector|7 years ago|reply
[+] [-] quotemstr|7 years ago|reply
[+] [-] stochastic_monk|7 years ago|reply
The C stdlib does not come with an AVL tree. Why would one not implement a b-tree in C for this comparison? It’s not as if K&R has “Use binary, not b-trees!” on the front cover.
[+] [-] vmchale|7 years ago|reply
[+] [-] abenedic|7 years ago|reply
A person should understand that no language(programming or otherwise) is perfect. Therefore there is some criticism of any language that is valid. Therefore some criticism should be taken seriously as there may be a real point to the criticism.
There are many posts like this, where there are comparisons of Rust to C. Realistically they are all a little biased towards Rust as Rust is a C++ replacement really. A more proper comparison would be Zig or D as a better C against C.
Just understand that a person defending C is not always an idiot, and maybe they have point. Consider the excessive memory use of any working Rust compiler. That will probably not be remedied anytime soon and is a legitimate complaint. The ideal of how something could be is not how something is. The reality is that C works pretty well most of the time, Rust works well most of the time. They both fail at some things.
[+] [-] vvanders|7 years ago|reply
You see a lot of people holding up Rust precisely because we've been there for the last 5/10/15/20 years. The day I don't have to write a makefile or build yet another CMakeLists.txt is the day I rejoice.
What Rust offers is another option in the native, non-GC'd language space. A space that has very few languages and even fewer yet that are shipped at scale. Rusts inclusion w/ FF means that the have to address the robustness, security, performance and usability of the language to a degree that you don't commonly see.
Having just blown 4+ hours today dealing with the linker on a mixed C/C++ project I don't really miss a lot of the baggage that comes with native development these days. Rust gives you the option of dropping down to that level while still preserving a set of sane, opinionated defaults that are pretty well thought out.
[+] [-] gnulinux|7 years ago|reply
[+] [-] blub|7 years ago|reply
I think they've also figured out that with time C will be squeezed into smaller and smaller areas of use, as is already happening.
Writing robust code hasn't really found a space to live in the mental model of C programmers. Using C outside a kernel or existing C project today is professional negligence.
[+] [-] nixpulvis|7 years ago|reply
Just one tiny gripe, don't use a blue and green next to each other in graphs if avoidable. I'm not even blue green colorblind, and I found them hard to distinguish.
Thanks for the great read.
[+] [-] solipsism|7 years ago|reply
[+] [-] quotemstr|7 years ago|reply
I'm not sure that comparing "Rust" and "C" performance is even meaningful. The latter is a multi-implementation language, and in most implementations, can be written in a way that gets the compiler to generate the same machine code that the Rust compiler does. (Frequently, they both just go through LLVM.)
[+] [-] kiriakasis|7 years ago|reply
when comparing languages you need to include a measure of how idiomatic your programs are.
[+] [-] p0nce|7 years ago|reply
[+] [-] stochastic_monk|7 years ago|reply
[+] [-] kiriakasis|7 years ago|reply
Of course it is entirely subjective (the author argues for how that is due to a static vs dynamic ownership model) and there is a single data point, which is the author rewriting the code. (two is you consider when he/she swaps one of the data structure)
[+] [-] ridiculous_fish|7 years ago|reply
[+] [-] lewisinc|7 years ago|reply
On instance of this becoming a complication would be in the GTK+ world with the Rust bindings to GObject. There's some really good articles about their adventures in that realm you could find.
[+] [-] tomjakubowski|7 years ago|reply
Meanwhile Rust, in this user's opinion, offers a superior toolset for modeling data and building behavior, namely: sum types and traits.
So if you're looking to extend or integrate with a C codebase, barring some exotic target platform and all else equal, I don't know why you'd opt for C++ over Rust.
[+] [-] pornel|7 years ago|reply
OTOH interfacing with C++ is very hard. D might be the only language that has seriously tried it, but from Rust's perspective C++ has largely overlapping, but incompatible set of features, and it's a weird dead-end.
[+] [-] marcosdumay|7 years ago|reply
[+] [-] saagarjha|7 years ago|reply
[+] [-] topspin|7 years ago|reply
That didn't happen. The data structure difference is discussed and the possibility of the performance difference being down to this is clearly acknowledged. Also discussed is the reason for the different data structures, which is actually the most important take-away.
[+] [-] dmpk2k|7 years ago|reply
It's one of the few high-quality technical articles that pass through HN... if you don't get hung up on the title.
[+] [-] stewbrew|7 years ago|reply
[+] [-] toolslive|7 years ago|reply
[+] [-] FartyMcFarter|7 years ago|reply
[+] [-] wffurr|7 years ago|reply
I can't speak for the author but at my work we found -O2 to give better results on our OpenGL ES rendering engine.
[+] [-] bowyakka|7 years ago|reply
[+] [-] dpc_pw|7 years ago|reply
[+] [-] nostrademons|7 years ago|reply
[+] [-] dxhdr|7 years ago|reply
[+] [-] UncleEntity|7 years ago|reply
Isn't rust based on LLVM?
It would make more sense, for a true apples to apples comparison, to use clang instead of GCC.
Not that I'm pro-C or anti-rust or anything but the beginning of the article goes on about previous tests not being fair.
[+] [-] kiriakasis|7 years ago|reply
At the end the author never states that one is faster (yes, the title is misleading, but it is then clearly clarified in the text) the main part is the discussion about intrusive data structures.