Live data from Hacker News

Why is Rust slightly slower than C?

github.com

101–110 of 251 posts

Re: Why is Rust slightly slower than C?

#101

Earlier quoted context omitted.

It is routine for C++ programs to be substantially faster than a C program that attempts the same job, even though C++ suffers from the same aliasing flaws C has. In the finance world, you would be laughed out of the room for proposing C for a performance-critical task. That depends on how you write your C++ programs. Virtual functions, runtime type information, STL, RAII ownership can all be performance hits in C++…

Is there really a performance cost from RAII? Presumably whatever a destructor has to do to release resources, C code would also have to do.

Indeed, RAII is a zero-cost abstraction compared to running the same destructors manually. On the other hand, C++ makes it really easy to write programs that copy and destroy things when it isn't necessary.

For example, if a function takes a `std::string` as an argument (by value), any string you pass in will be copied into a new allocation, which will then have to be deallocated. That's fine if the function really needs its own allocation – but it might not. In that case you can avoid the copy by changing the argument type to `const std::string &` or `std::string_view` (the latter being new in C++17)... but the difference is subtle enough that even an experienced programmer might not notice the extraneous copy.

Don't believe me? Consider that in 2014, "std::string was responsible for almost half of all allocations in the Chrome browser process"! [1]

(Rust does a better job here by requiring more explicitness if you want to make expensive copies.)

Oh, there's also an issue where the presence of a destructor pessimizes the calling convention for passing and returning objects of that type by value, but only slightly, and the issue will be addressed in the future. [2]

[1] https://groups.google.com/a/chromium.org/forum/#!msg/chromiu...

[2] https://quuxplusone.github.io/blog/2018/05/02/trivial-abi-10...

Re: Why is Rust slightly slower than C?

#102

Earlier quoted context omitted.

Bounds checking is a “zero cost abstraction” in the sense that it is both “pay for what you use” and “you couldn’t implement it yourself any better.” That said, the implemention is not as fast as it theoretically can be, because the compiler isn’t always removing bounds checks that are provably true. When const generic lands, you will be able to make those assertions! A basic implementation is in nightly.

how do you not use bounds checking? (unsafe like get_unchecked doesn't count because then you can say that about almost every rust feature).

You're mis-understanding what "you don't pay for what you don't use" means. It means that a program that does not contain [] in it does not include code for []. There's no "mandatory runtime" code for []. It doesn't mean you can use [] in some special way and somehow get less code.

And even if we were talking about your understanding, I don't see why get_unchecked would be disqualified. unsafe is a part of the language for a reason.

Re: Why is Rust slightly slower than C?

#103

I wonder if some of the bounds checks could be eliminated by using iterators instead of loops? It is common when coming from C to Rust to sometimes avoid complicated iterators because you imagine it can't be fast, so you use a loop, but usually the iterator really is faster. And I believe the checked math can be eliminated just by explicitly stating you want to use unchecked math. It doesn't require unsafe to do so.

iterators had a lot of work done on them for this reason. although it doesn't always work.

eg, once the difference between using a sign and unsigned value in a loop was causing tustc to not be able to optimize out the checks and resulted in terrible performance for that loop, but it was non-trivial to figure this out

Re: Why is Rust slightly slower than C?

#104
post #58
post #42

Earlier quoted context omitted.

Yeah, their initial explanation is that its the "safety features", but I was under the impression that literally everything related to rust's safety happens at compile time. Their big selling point is the "zero cost abstractions".

Their initial explanation is bounds checking specifically. While most abstractions are zero-cost, bounds checking isn't. I do wish there were a way to track expectations about integer ranges in a type system, but there currently aren't.

This got me wondering why we don't include dedicated hardware for bounds checking in CPU architectures. Intel made an attempt with MPX but from a brief glance on Wikipedia it looks like a fail (slower than pure software approaches like AddressSanitizer, among other issues).

Re: Why is Rust slightly slower than C?

#105
post #101

Earlier quoted context omitted.

Is there really a performance cost from RAII? Presumably whatever a destructor has to do to release resources, C code would also have to do.

Indeed, RAII is a zero-cost abstraction compared to running the same destructors manually. On the other hand, C++ makes it really easy to write programs that copy and destroy things when it isn't necessary. For example, if a function takes a `std::string` as an argument (by value), any string you pass in will be copied into a new allocation, which will then have to be deallocated. That's fine if the function really n…

even if you take the string as `const std::string &` you will still end up with implicit string construction if someone passes a char* . Sure you can use std::string_view as an argument type to prevent this simple case, but it doesn't work in all cases.

Consider a std::map for example, if you have a char* and you want to index in to the map you are going to also end up with an intermediate string construction b/c STL associative containers don't have heterogenous lookup. Note that this was fixed in std::map::find in C++14 [0], but still is there for operator[].

[0] - https://en.cppreference.com/w/cpp/container/map/find

Re: Why is Rust slightly slower than C?

#106
post #68

Earlier quoted context omitted.

How current is this impression? There continue to be first-rate Fortran compilers that probably win on numerics for exactly the reasons you state, but I would be surprised that PL/I has a toolchain that's kept up with modern architecture. String handling, on most modern toolchains, mostly goes to inline functions or builtins that the compiler has been (rather pragmatically, if a big disgustingly) made aware of. It's…

My experience is old, but my summary point remains: Language defined and compiler supported functionality usually is faster than libraries of external functions. The relevance here: C isn't the fastest thing around and can be beaten. Maybe similarly for Rust. For PL/I and strings, for the IBM versions on S/360 and S/370, the compiler might have used some of the hardware instructions for string handling. I'd be surpri…

C/C++ compilers will happily optimize standard library functions. A call to printf that doesn't use any % formatting will usually get converted into a call to puts, for example. And strlen of a string literal is of course replaced with a constant integer, and strcpy will be converted to memcpy if the length is known. And memcpys of known length are of course emitted with appropriate move sequences.

Re: Why is Rust slightly slower than C?

#107
post #75

C is the wrong language to compare to. More precisely, Rust should be able to beat C, routinely. Presumably it will, when it gets more optimizer attention. With any luck, that improvement can go into LLVM proper, and speed up many other languages besides. Why should Rust beat C? First, it does not suffer from the pointer aliasing faults C has. Second, const really means const, where in C the compiler has to assume an…

Is there an element of runtime correctness and safety as well? Are we comparing programs that have proper bounds checking to ones that don't?

Re: Why is Rust slightly slower than C?

#108
post #75

C is the wrong language to compare to. More precisely, Rust should be able to beat C, routinely. Presumably it will, when it gets more optimizer attention. With any luck, that improvement can go into LLVM proper, and speed up many other languages besides. Why should Rust beat C? First, it does not suffer from the pointer aliasing faults C has. Second, const really means const, where in C the compiler has to assume an…

I didn’t realize it was possible to be so wrong.

Ok, but please don't be rude or post shallow dismissals here. If you know more, it would be great to share some of what you know. Then we can all learn something. Alternatively, it's fine not to post even when someone else is wrong.

https://news.ycombinator.com/newsguidelines.html

Re: Why is Rust slightly slower than C?

#109
post #10
post #3

I'm surprised how much bloat rusts adds and how little it affects the speed. Is there any other downside? Electricity consumption / heat? Evicting other stuff from cache?

We can see in this specific case there was better cache locality and more data was served from the L1 and L2 cache with a drop in L3 cache misses (no hits, because it didn’t have to look in L3 for anything). 6 cycles for bounds checks that the branch predictor never had to rewind on is nothing in comparison to saving a couple trips to L3.

Presumably a C++ (or SaferCPlusPlus[1] ;) implementation would see a similar cache performance advantage versus C?

Also, isn't it unintuitive that branch mispredictions go up with larger batch sizes? Wouldn't there be fewer branches per unit time?

[1] https://github.com/duneroadrunner/SaferCPlusPlus/blob/master...

Re: Why is Rust slightly slower than C?

#110
post #80
post #78

Earlier quoted context omitted.

That isn't "type checking", that is just a guard to prevent simultaneous writes to the same data.

You're correct- what I had meant to say is Rust is smarter with more runtime checks over C for several cases, like RefCell. Therefor, Rust can be slower than C because of safety (but not because of type checking itself).

RefCell has an internal semaphore. It's used specifically for multi threaded scenarios.

If someone is writing a multi threaded C app, they will likely be using semaphores as well. At least, they should be. Rust just enforces it.

So, I wouldn't say rust is "slower" in the regard.

Post reply on HN