The examples I have seen where a Rust rewrite is faster than original C++ code usually have glaring performance issues in the C++: Often, it is code that does a ton of unnecessary copies. The Rust code often doesn't copy as much because the Rust language makes that kind of copying inconvenient or because the person doing the rewrite is a Rust expert and not a C++ expert. The other kind of speedup I have seen is when people swap a C++ std::map for a Rust btree_map, and don't realize that absl::btree_map (a C++ btree map in Google's library) is what Rust's btree_map is based on.
I haven't seen any examples where C or C++ code written with performance in mind gets a rewrite to Rust and goes faster, and I have seen the opposite.
Cliff Biffle's great series of blog posts called "Learn Rust the Dangerous Way" takes the fastest C program from a benchmark game entry, rewrites it naïvely in Rust using copious amounts of `unsafe`, and then transforms it into program without `unsafe` while keeping it idiomatic. The last version is faster than the C implementation.
It's a toy example but it's real-world example.
However, the benchmarks game (and microbenchmark-based comparisons in general) is hard to take seriously if you are thinking about application performance. Some languages microbenchmark very well, but don't translate that to system performance (C is the poster child of this effect), and some microbenchmark poorly but work very well in practical systems (Go is the most popular language with a big gap here, but some functional language like OCaml or Haskell probably has the biggest gap).
The reasons for these gaps can include things like it being harder to use the optimal data structure for your application (eg C code using red-black trees instead of btrees in 2023) and large code size causing terrible caching behavior (heavily templated C++). I also remember seeing something here about some non-optimal calling convention in the Rust compiler, which would be another thing that shows up in a system that doesn't in a microbenchmark.
Microbenchmarks are not a good replacement for system-level comparisons.
Even when we're shown "Benchmarks are a crock" ?
https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
> Microbenchmarks are not a good replacement for system-level comparisons.
For example —
https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
Instead, the main arguments for the claim that Rust is the same speed as C++ are microbenchmarks, which actually are pretty useless when you are comparing very different implementations. The time they are useful is when you are refining an implementation.
If you want to scrutinize the benchmarks game even further, they use gcc for their c compiler, where clang would probably be a better choice since the benchmarks are arithmetic-heavy.
> The reasons for these gaps can include things like it being harder to use the optimal data structure for your application (eg C code using red-black trees instead of btrees in 2023)
Bryan Cantrill described this experience[1] and maybe that is exactly what you are referring to.
But if you're just looking for a language to get work done with, does it matter if Rust is faster because of better off-the-shelf data structures and algorithms or because of some inherent magic in the programming language?
[1] See point 9 here: http://dtrace.org/blogs/bmc/2018/09/18/falling-in-love-with-...
I don't already know C++. For me, learning Rust is easier than learning safe C++. I imagine that there are many people in a similar situation for whom Rust makes more sense than C++. That doesn't mean that it makes more sense for everyone.
And would cost someone else real money to do — so microbenchmarks ;-)
> … they use gcc for their c compiler, where clang would probably be a better choice…
https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
"Milli benchmarks are not really hard
Micro benchmarks are challenging, but OK
Nano benchmarks are the damned beasts!"
Slide 19
For the companies that re-wrote their databases, login systems, and other similar things in Rust, a real benchmark comparison would be pretty easy, and they probably did it internally anyway. Hook one of your servers up to an artificial load generator and see how much it can take.
Personally, I read that as "can be as fast as, but without you having to be Willy Tarreau level genius" which is all I need.
It's easier/more-intuitive to do a lot of things in C++, but safe, high performing C++ is certainly harder than safe, high performing Rust for huge swaths of use-cases. Also, as has been mentioned, its type system that benefitted from the PL research since the 80s also allows for nicer expression of business logic. In particular, this means that in Rust, unlike C, Go, or even C++ in great part, you are not writing in the same low-level intricate language at every level of your stack i.e. it can be a nicer high-level experience the higher you go if you designed your lower tiers well.
And that last thing to me is the biggest advantage it has over the competition.
Off course, there is also the fact that juggling dependencies in a non-trivial C++ project was a nightmare until recently with vcpkg and it's manifest mode and that will take probably another decade to become commonplace in the ecosystem (if ever).
[1]: https://github.com/bparli/convey [2]: https://bparli.medium.com/adventures-in-rust-and-load-balanc...
https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
Which is my biggest gripe with benchmark games. There really ought to be strict categories for "straightforward, idiomatic code someone with 3 YoE could write", "optimized-but-still maintainable code an experienced senior engineer would write", and "unrestricted wizardry".
> … straightforward, idiomatic code…
Even with tiny programs, once you ask for "idiomatic code" things stop being straightforward: different languages do things differently —
https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
> … hand-written SIMD…
One approach is to filter those programs into their own section — hand-written vector instructions | "unsafe".
Another is to use source code size as a proxy —
https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
But it would be interesting to try to approximate something like those categories. The project repo[1] contains the following call for idiomatic code:
Please, people ask to see more "idiomatic" programs —
- we already have enough exhaustively optimized Rust and C programs.
- we already have enough hand-written vector SIMD and "unsafe" programs.
Thank you.
[1] https://salsa.debian.org/benchmarksgame-team/benchmarksgameOn this subject... it's much easier to become a Rust expert than a C++ expert.
I do expect the world to have more Rust experts than C++ ones today, even with much lower usage of the language and much less time for people to learn it.
Often, code written in C / C++ does unnecessary copies precisely because the risk of avoiding those copies is hours of debugging, crashes in production, or security flaws.
So this is a legitimate benefit of Rust. Being able to code more aggressively up front, without fear of something blowing up in your face later, or much later when the intern touches the wrong line.
>I haven't seen any examples where C or C++ code written with performance in mind gets a rewrite to Rust and goes faster, and I have seen the opposite.
Here's one from Bryan Cantrill
http://dtrace.org/blogs/bmc/2018/09/28/the-relative-performa...
The point he makes is that while Rust is not strictly faster than C in most cases, it gives you the comfort of being able to use more highly optimized libraries and data structures without needing to have the extreme level of trust in the author that you do in C / C++. This is basically the same argument.
Compared to C, where a data structure library is at best a heap of cobbled-together macros that make a lot of assumptions about the underlying types, C++ has well-developed libraries for all of the data structures mentioned.
And you need to trust the author plenty to make a btree that works - that is a very complicated data structure. It's not just about memory safety, there can be a lot of functional bugs, too. The author of the C++ one is Google/Facebook, who I trust to write a solid library, while the author of the Rust one is someone who was inspired by the C++ version.
At this point, both are well-tested, but there are a lot of Rust libs that are in the same position, but relatively untested.
The language-change whiplash that people accuse Rust of happens to C++ folks who leave the language for several years, since "idiomatic" C++ has changed substantially over the last 20 years.
EDIT - Just to clarify, there are SO MANY different ways to do things in C++ that the way to really learn C++ is by reading (both good code and the spec), not by writing. It's very easy to write a ton of code and not actually do it in the fastest/best/most idiomatic way. This is complicated by the fact that a ton of C++ examples out there are wrong. It's really an electrical engineer's language at this point - read all the datasheets if you want to avoid getting shot in the foot (and still get shot in the foot anyway).
E.g., will the C++ rewrite for X improvement take longer, or require a more highly skilled programmer, or would the Rust programmer require some high level of expertise to yield the results but a junior C++ guy/gal could knock it out quickly?
Has anyone done real comparisons of this sort, such as taking software package X and assigning a performance rewrite to a junior Rust dev, a senor Rust dev, a junior C++ dev and a senior C++ dev, giving each a couple weeks then checking the yielded performance?
Also, how does this interact on teams? It's been a long time since I've written any C++, and I've not tried Rust, but it seems some of the Rust safety features make it harder for devs to step on each other's toes.