Live data from Hacker News

Why is Rust slightly slower than C?

github.com

51–60 of 251 posts

Re: Why is Rust slightly slower than C?

#51
post #50

Earlier quoted context omitted.

> Rust is strongly-typed, is it not? Yes, at compile-time. > Does it do run-time type-checking? No. The closest thing is the occasional vtable-based dynamic dispatch. > Exception handling in particular requires a non-negligible amount of run-time overhead Wouldn't the side-table approach be used? That has essentially zero cost, if an exception is not thrown.

Well again -- I don't know how Rust does it specifically, but when you compile C++ programs in g++ with exceptions disabled you pretty consistently see a 10% speed improvement right off the bat and the performance falls more closely in line with the performance of C code. Specifics aside the broader point is that the runtimes between the two languages will differ.

Huh, that surprises me.

g++ exceptions have been touted as zero-cost for the happy path.

https://stackoverflow.com/a/13836329

http://www.hexblog.com/wp-content/uploads/2012/06/Recon-2012...

Re: Why is Rust slightly slower than C?

#52

Earlier quoted context omitted.

Really no point to running it without real hardware, it will perform completely differently if you don't have the MMIO accesses and DMA by the NIC in there. We'll have a VirtIO driver soon, but that's bottlenecked by the hypervisor and not really useful for performance tests.

With fake memory mapping it would not access the same memory, but you'd still run the same code, right? So the timing/details of access may change a lot, but the profile of executed code would be still meaningful. For example, if you run a loop with range checks, and a loop without them, it doesn't matter what's happening in the loop, as long as it stays consistent between the runs - you can still tell things about t…

Would need a somewhat realistic emulation of the NIC setting/clearing these flags. Also, the by far slowest steps are the MMIO access because it involves a full PCIe round trip which is hard to emulate.

It will behave different at the level we are looking at here. It's easier to use real hardware; we specifically chose this NIC because it's probably the most common 10G NIC on servers.

Re: Why is Rust slightly slower than C?

#53
post #42

Because C is slower than C. That is, they are compiling C with GCC, but Rust uses LLVM as a backend. Compiling their C code with clang reveals that it is also slightly slower than the C code compiled by GCC, but not faster than Rust. The actual conclusion here is that the GCC toolchain is slightly faster than the LLVM toolchain for this particular use case, but that isn't really news - it happens all the time. If one…

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".

I don't know... while it may not be the case here, I wouldn't be exactly shocked if the fact that Rust restricts your ability to do some things ends up having a performance penalty, even if any safety checks themselves happen at compile time.

Re: Why is Rust slightly slower than C?

#54
post #21

Earlier quoted context omitted.

I'm curious if there is a discussion thread on that design choice.

I’m not 100% sure if there’s a source exactly, but we don’t like safety and correctness to depend on what flags you pass or do not pass. We don’t offer a fast-math flag either for similar reasons. The odd one out is overflow, and that’s only because it’s well defined (a “program error”) and not UB to overflow in Rust. This gets checked in debug but not currently release, though the spec allows for it.

I guess my thought is that much of correctness comes from the compiler being able to make assertions that some type (and thus some memory address) will only be used in a correct way at compile time, etc, etc.

For example if we were dynamically linking a Rust crate into a Rust binary is it necessary to check boundaries in both or can some of that be deferred because we can assume the binary that will link has already done the boundary checks, etc?

I know it's a bit contrived since ideally we'd just compile statically, but I think it's still potentially valid. If both pieces of software have the guarantees then ideally you can factor out some of the overhead.

Re: Why is Rust slightly slower than C?

#55

As an aside, can I just say how happy I am that the language I generally find a joy to use is nearly as fast as C? It's my daily driver, and I have almost no complaints. I really do love this language.

Nearly? Rust is already faster than C in quite a few scenarios and benchmarks. The other comment also said Rust is faster when C is compiled through clang.

Re: Why is Rust slightly slower than C?

#56
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.

> We can see in this specific case there was better cache locality

Dramatically better L1 and L2 cache behavior. It seems clear that the additional instruction load of the Rust driver is partially made up by the excellent cache utilization.

This "Rust vs C" document is just one part of a larger analysis of network driver implementations in many languages; C, Rust, Go, C#, Java, OCaml, Haskell, Swift, Javascript and Python. Have a look at the top level README.md of that GitHub repo.

Re: Why is Rust slightly slower than C?

#57
post #44

The two biggest factors involved are (1) Runtime. Even though C has "no" runtime, there is some runtime overhead: Variable allocation / de-allocation and alignment. Function invocation / call stack setup. Et cetera. I don't know enough about Rust to understand what its exact "runtime" is like, but I'd bet it's not exactly like C. (Rust is strongly-typed, is it not? Does it do run-time type-checking?) Exception handli…

Others have pointed out that Rust's type-checking is all done at compile time. Rust also does not have exception handling.

To be more specific: errors in Rust are either propagated by function return values (usually in the form of `Result` or `Option` types) which do not require any kind of runtime support, or by panicking, which unwinds the stack for clearing-up of resources and then halts the running thread. (Panics cannot be caught, although they can [EDIT: sometimes but not always; see burntsushi's comment below] be observed by a parent thread if they have occurred in a child thread.) Rust's "runtime", therefore is negligible, much like C's: it consists mainly of functions which can be called for things like stack unwinding or backtrace support.

Re: Why is Rust slightly slower than C?

#58
post #42

Because C is slower than C. That is, they are compiling C with GCC, but Rust uses LLVM as a backend. Compiling their C code with clang reveals that it is also slightly slower than the C code compiled by GCC, but not faster than Rust. The actual conclusion here is that the GCC toolchain is slightly faster than the LLVM toolchain for this particular use case, but that isn't really news - it happens all the time. If one…

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.

Re: Why is Rust slightly slower than C?

#59

Looking at performance counter data is good, but I would have liked to see a real validation of the hypothesis that bounds checking is to blame for the extra branches and instructions. That is, modify the Rust compiler to not emit bounds checks (or maybe there is even a flag for this?) and look at performance and counters. I would imagine that this would bring the data for Rust to pretty much the same as C. But other…

> (or maybe there is even a flag for this?) We specifically do not give you a flag to control this behavior, but you can choose to call different functions to use unchecked access.

This, imo, is absolutely correct (it is a dark idea to have a "let's be unsafe for more performance" flag) but maybe a experimental build of the Rust compiler could have this as a configuration option? Possibly the toolchain could warn every step of the way if such a 'tainted' module is ever linked, etc.

It just seems like this sort of question is going to recur, and being able to persistently track the overhead of checking (it would allow you to monitor specific performance improvements) is much nicer than having someone do a one-off experiment.

Re: Why is Rust slightly slower than C?

#60
post #37

On how "fast" C is, guys, sorry to say this, but in my experience actually (1) even assembler is not very "fast", (2) for much the same reasons C is not very fast, (3) often Fortran is faster than C, and (4) PL/I can be the fastest of all of (1)-(4). More generally, how Fortran and PL/I can be faster than C should be exploited quite generally but apparently has not been fully generally. Why? How can Fortran and PL/I…

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 very unlikely that strcpy or memmem is going through external linkage.

Post reply on HN