Live data from Hacker News

Rust is now overall faster than C in benchmarks

benchmarksgame-team.pages.debian.net

311–320 of 445 posts

Re: Rust is now overall faster than C in benchmarks

#312

Earlier quoted context omitted.

You'll be happy to know I implemented the n-body benchmarks game in zig 0.6.0 and it absolutely thrashed the rust version. Submitted it, but they don't take PLs not on the board currently.

But how much? Do you have an idea why?

Honestly I have no idea. You can try it yourself, or put it through godbolt:

https://gist.github.com/ityonemo/f34e0d3b4891f481863980a3142...

Note it could also be platform dependent. I'll give it a whirl on my own (new) machine.

Re: Rust is now overall faster than C in benchmarks

#313

Earlier quoted context omitted.

The reason that C programs often perform well is that it’s so incredibly hard to do anything at all in C (especially something reliable) that one can usually only do the simplest thing possible and this typically means simple data structures, simple algorithms and arrays. In many ways, modern CPUs are particularly designed to run the machine code generated by C compilers on typical C code like this. Pointers and memo…

Fascinating. I would’ve thought most commercial C programs would have heavily used linked lists, hashes (dictionary), and binary search trees all over the place. I assume most C++ programs heavily use more of these advanced data structures, correct?

Heavy use of linked lists is one reason for why commercial C code often is slow. While there are some exceptions linked lists are slower than arrays for most things. Linked lists are easy to implement in C and therefore used a lot.

Re: Rust is now overall faster than C in benchmarks

#314
post #194

Earlier quoted context omitted.

Null terminated strings are often called cstrings. They’re beyond idiomatic; they’re part of the C standard library.

Not just the standard library, but the core language. They are what you get if you write a string literal in your code.

Yes but if we are being pedantic no. Of course the language does still greatly lean into the null terminated string concept.

You get a null terminated char array but the length is actually available since arrays (as long as they haven't decayed into pointers) can still share their length at compile time.

Re: Rust is now overall faster than C in benchmarks

#316

Earlier quoted context omitted.

But how much? Do you have an idea why?

Honestly I have no idea. You can try it yourself, or put it through godbolt: https://gist.github.com/ityonemo/f34e0d3b4891f481863980a3142... Note it could also be platform dependent. I'll give it a whirl on my own (new) machine.

Do you think that it may be caused by use of comptime? I have not looked at the benchmark implementations, but that kind of struck me as a reason

Re: Rust is now overall faster than C in benchmarks

#317
post #143

Earlier quoted context omitted.

restrict and strict aliasing have to do with the same general concept, but aren't the same. They both have to do with allowing the compiler to optimize around assuming that writes to one pointer won't be visible while reading from another. As a concrete example, can the following branches be merged? void foo(/*restrict*/ bool* x, int* y) { if (*x) { printf("foo\n"); *y = 0; } if (*x) { printf("bar\n"); } } Enabling s…

OK thanks, indeed Clang is able to generate better assembly using __restrict__. And -O3 generates the same assembly as -O3 -fstrict-aliasing (which is not as good as __restrict__). I wish there was a C/C++ compiler flag for treating all pointers as __restrict__. However I guess that C/C++ standard libraries wouldn't work with this compiler option (and therefore this compiler option wouldn't be useful in practice).

What's interesting to note though is that I tried marking pointers __restrict__ in the performance critical sections in 2 of my C++ projects and the assembly generated by Clang was identical in all cases!

So while it is true that by default Rust has a theoretical performance advantage (compared to C/C++) because it forbids aliasing pointers I wonder (doubt) whether this will cause Rust binaries to generally run faster than C/C++ binaries.

On the other hand Rust puts security first, so there are lots of array bounds checks in Rust programs (and not all of these bounds checks can be eliminated). Personally I think this feature deteriorates the performance of Rust programs much more than you gain by forbidding aliasing pointers.

Re: Rust is now overall faster than C in benchmarks

#319

I was wondering if perhaps this was actually measuring a difference between LLVM and GCC, but they also provide a set of benchmarks of C Clang vs C GCC (1) and Clang is generally slower in those test. Although there is some correlation between the ones Clang wins in C And Rust. 1. https://benchmarksgame-team.pages.debian.net/benchmarksgame/...

Rust can be faster than C because in general C compilers have to assume that pointers to memory locations can overlap (unless you mark them __restrict). Rust forbids aliasing pointers. This opens up a whole world of optimizations in the Rust compiler. Broadly speaking this is why Rust can genuinely be faster than C. Same is true in FORTRAN, for what it's worth.

In theory one day Rust will but LLVM doesn't support anything beyond the function level for noalias since that's all that's needed to support __restrict in C. Even that isn't used by Rust most of the time since they have found several bugs in it.

Re: Rust is now overall faster than C in benchmarks

#320

Apart from those benchmark games a lot of real world C is a lot less performant than people think it might be. I spent a fair amount of time reviewing C code in the last 5 years - and things that pop up in nearly every review are costly string operations. Linear counts due to the use of null terminated strings and extra allocations for substrings to attach null terminators, or just deep copies because ownership can’t…

The reason that C programs often perform well is that it’s so incredibly hard to do anything at all in C (especially something reliable) that one can usually only do the simplest thing possible and this typically means simple data structures, simple algorithms and arrays. In many ways, modern CPUs are particularly designed to run the machine code generated by C compilers on typical C code like this. Pointers and memo…

>The reason that C programs often don’t perform as well as an equivalent rust program[1] is that it’s so incredibly hard to do anything at all in C (especially something reliable) that one can usually only do the simplest thing possible and this typically means simple data structures, simple algorithms and arrays

Reliability is very often the name of the game with C, and part of the reason you might see it written in such a simplistic fashion. In embedded systems, we often follow very strict code convention that has strict requirements on how a C program is to be written. This includes everything from how memory is to be allocated, the maximum number of local variables, the maximum number of the arguments, various limits on a function, constraints to handle errors, etc. We do this because it minimizes potential hazards especially when working with limited memory and system resources.

C is an unforgiving language in that mistakes can occur silently and on mission critical hardware these mistakes can cost more than just your project milestones. These programs are very specialized and often have complex algorithms associated with them. Most of the systems I've worked with include various kinds of feedback control systems, and accompanying algorithms. If you're familiar with control systems, you'll know these algorithms are certainly not trivial by any means.

The challenge with C is more as a developer your C code needs to be perfect. Bugs just aren't an option like they are in other environments. Once a specialized piece of hardware ships it needs to work as intended under a myriad of conditions without powering off for the next 30 years (not always the case but more often than you might think). Sometimes this kind of software is going to be put a position it may have never been designed for. The best we can do is try to add various check/support mechanisms both in software and in hardware, and maintain as safe and hazard free software as possible.

In terms of performance, again coming from an embedded environment, there is almost always a spec we are aiming for. It needs to do X tasks in N time for example. Of course high level design questions like whether to poll or wait for interrupt, or how to broker data from shared resources is decided long before you get to the question of how should I, or if I even should, compare two strings. It is nevertheless advised to go with a trivial solution if the ends satisfy the needs.

Is C time-consuming to write? Is C a "hard" language? These are subjective and depend on the nature of the project. I would certainly never use C with only libc to write a webserver that's going to be serving SaaS Co's backend API.

Post reply on HN