Rust is slow (semi clickbait)

Hello,
Sorry for the (kinda) clickbait title. The main issue is that Rust’s tooling is very slow, particularly on windows subsystem for linux, running Ubuntu. Building the “hello world” program using cargo typically takes more than 20 seconds. On the same machine and configuration, GCC does it in about 3-4 seconds. Rustup takes about 15-20 minutes to execute - all of the steps are fairly fast, but it gets hung up on the “installing rust-docs” step. Is “rust-docs” necessary for the usage of Rust? If not, could you add an option to not download / install it? To avoid being flagged as clickbait, also, the output generated by the Rust compiler in release configuration is also slower than expected - right now, it’s a little slower than C++. Rust has strict pointer aliasing rules, so, in theory, it should be faster than C++.

That seems really excessive.

You should add an exception for Rustup’s directory in Windows Defender though; that’s probably why rust-docs takes so long.

1 Like

With all due respect, the statement about strict pointer aliasing necessarily leading to faster code is very naive. In addition:

  • It seems like you’re comparing C++ compiled with gcc vs Rust, which is compiled by LLVM; if you at least want to keep the comparison in the realm of the same optimizer, you should compare against C++ compiled with clang.
  • What is “a little slower” in terms of measurement?
  • Are you sure your Rust code is a fair translation of the C++ code?
1 Like

No, the whole WSL directory is not scanned by Windows Defender.

Those aren’t my benchmarks - I got them from “the benchmarks games”. Probably not the most reliable source, though. You can see that C++ has a very low execution time with low spread. C has a lower (but almost identical) mean time but has more spread, while Rust has a mean that’s noticably higher and more spread than C++. All things being fixed, though, the strict pointer aliasing should, in theory, give the compiler more information and allow it to optimize more aggressively.

What is the performance when not in a virtualised environment.
Have you checked to see if the benchmarks are explicitly using SIMD.

From what I have read, strict pointer aliasing is where the compiler makes accessing the same variable with different types be UB. Rust allows this, so is no-strict.

let f:f32=1.0;
let p = &f as *const _ as *const u32;
println!("{}", unsafe { *p });

I don’t think there has ever been an expectation the aliasing rules would give dramatic performance boost, still nice to have any little gain though when the development cost is low.

@ndrewxie is (very likely) talking about simply aliasing information in Rust, i.e. &mut T being a unique alias to the value. But yeah, all else equal it can yield slightly better code generation (which in some loop may yield noticeable perf boost), but all else isn’t equal :slight_smile:.

1 Like

Regarding the benchmarks game, in the past Rust had a hard time to compete in some challenges because of missing (stable) SIMD support. Since stable SIMD is very recent, this might be still the case if nobody stepped up to update the entries.

There are also some suboptimal rules enforced in the vein of “if the language has a standard hashtable, it must be used, if not, you can include/use the fastest library available”.

2 Likes

Indeed. Yes, I am.

FWIW this is not entirely accurate anymore, and that issue has been fixed.

2 Likes

I agree rust-docs is both a waste of installation time and download time/data. So I’d like a way to not install it every Nightly.

Also, the Rustup still hangs at the end of the installation.

3 Likes

Great to hear!

Hmm… Anything about the Rust language itself that makes things “not equal”? From what I’ve seen, LLVM generates slower code than GCC… maybe create / add multiple backends?

AFAIK there are plans to have multiple backends eventually (like cretonne/cranelift), but it’s a large amount of work, and the amount of work the compiler team can do is not infinite.

As for slow install of rust docs, it’s most likely entirely caused by slow filesystem. If you’d like to make the docs optional, there’s an open issue for this.

2 Likes

OK, thanks!

With respect to C++ I guess? Nothing super fundamental - the difference could be in one or two (missed) optimizations by the backend, in either direction. There’re things like no const generics in Rust, but that’s being worked on. C++ can exploit some things it defines as UB, such as signed int overflow - under certain conditions it may allow loops to be more optimized. But then Rust has its own advantages (e.g. better alias info, as discussed in this thread); and one of these advantages may lead to better practical performance: “fearless refactoring” :slight_smile:. People are more likely to undertake intrusive refactoring in a large Rust codebase than a large C++ one, because the compiler will detect a whole slew of problems that C++ would be silent on.

Yeah, that’s a commonly held belief although it’s probably very nuanced (i.e. some optimizations might be better in LLVM while others in GCC, LLMV/GCC use different inlining approaches, some arch-specific backends are better than others even within a single compiler backend, etc).

3 Likes

This is almost certainly a WSL issue. Here’s timings for the “native” MSVC Rust toolchain on my not-so-recent Windows laptop:

cargo new --bin hello_world
     Created binary (application) `hello_world` project

cd hello_world/

cargo build
   Compiling hello_world v0.1.0 (file:///C:/temp/hello_world)
    Finished dev [unoptimized + debuginfo] target(s) in 0.66s

WSL is an amazing piece of technology but nobody has ever accused it of being fast.

8 Likes

Oh wow. The filesystem of WSL definitely isn’t fast, but… cargo build takes about 20 seconds for me on the hello world program, 0.66 s for you? So WSL is 33 times slower. Wow, just wow… WSL is already excluded from windows defender. Strange, because GCC doesn’t have this problem, even for large projects (I’m using the linux kernel as the canocial large project).

Could that have anything to do with rustc's compilation model? I’ve found that it’ll generate loads of small-ish files under the target/ directory, especially when it comes to incremental compilation. Maybe that combines with the WSL filesystem to make everything slower?

Rust programs also tend to pull in more dependencies than C programs (as one datapoint, mdbook is around 7k lines but cargo vendor puts around 1M lines of Rust code in vendor/) which would probably lead to rustc needing to compile more code in “real” applications.

That said, taking 20 seconds to compile a hello world program is quite excessive. I’m running on a Linux machine and it takes about 0.2-0.3 seconds to compile in release mode…

$ cargo new --bin hello_world
     Created binary (application) `hello_world` package
$ cd hello_world
$ cat src/main.rs 
fn main() {
    println!("Hello, world!");
}
$ time cargo build
   Compiling hello_world v0.1.0 (/tmp/hello_world)
    Finished dev [unoptimized + debuginfo] target(s) in 0.26s
cargo build  0.20s user 0.07s system 98% cpu 0.276 total
$ time cargo build --release 
   Compiling hello_world v0.1.0 (/tmp/hello_world)
    Finished release [optimized] target(s) in 0.19s
cargo build --release  0.16s user 0.05s system 98% cpu 0.210 total

hmm… I’ll try on Windows (native)