Live data from Hacker News

Why is Rust slightly slower than C?

github.com

141–150 of 251 posts

Re: Why is Rust slightly slower than C?

#141

Earlier quoted context omitted.

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 langua…

I know, the meaning of "zero cost abstraction" is really "zero cost to not use the abstraction." But that's like saying if you don't use rust you don't pay for it. Just because there is the unsafe escape hatch in the language, you don't get to label the language as zero cost abstraction. Because practically speaking there is a lot more runtime cost to rust than people will tell you. Many langauges (almost anything wi…

You still seem to be missing the point.

If you use a Rust construct that does bounds-checked accesses, you're explicitly using bounds checks. You're not paying for anything beyond the bounds checks that you're using.

If you use a Rust construct that elides the bounds checks (e.g. get_unchecked), there are no bounds checks, and you don't pay any cost for the fact that Rust supports a bounds-checked subscript operator.

If you want to compare Rust's subscript operator, do so with an explicitly bounds-checked version of the C code. That's the appropriate comparison for "zero-cost abstraction". Because the whole point of "abstraction" is it's not a change to the observed runtime behavior, it's just a language abstraction.

Re: Why is Rust slightly slower than C?

#142
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…

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++…

Nowadays, it is ironic given how bad C compilers used to generate code all the way up to the late 90's.

Re: Why is Rust slightly slower than C?

#143
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…

This is a great comment, but it's in the wrong place. The OP is about using Rust/C to compose network and packet handling software; using Fortran there would be completely pointless. There is no easy gain to be found from vectorization in networking.

I was not bringing up vectorization in Fortran. E.g., in Fortran we can have

     Real X(20, 30,40), all

     Call addall(X, 20, 30,40, all)
and have

          Subroutine Addall (Z, L, M, N, Result)

          Real Z(L, M, N), All, Result

          Integer L, M, N, I, J, K

          Sum = 0.0
          Do 100 I = 1, L
          Do 100 J = 1, M
          Do 100 J = 1, N
          All = All + Z(I, J, K)
     100  Continue
So what is good here is that in the subroutine the parameter Z gets its array bounds PASSED from the calling routine, the statement

     Real Z(L, M, N)
honors those bounds, and the code then does the indexing arithmetic (row major or column major, I don't recall which) using the bounds passed as arguments to the parameters L, M, N. That is, in the subroutine we can have the array bounds as parameters, and still Fortran does the array indexing arithmetic.

Can't do that in C: In C the programmer has to do array indexing with their own code in the subroutine. Thus to the compiler this code is just ordinary code and has to be treated as such. In contrast array indexing Fortran does is not from ordinary code thus permitting Fortran to make better use of registers and, for example, leaving intermediate values in registers and not writing them back to storage in variables known to the source code.

Here vectorization has nothing to do with it.

Bluntly, C doesn't support arrays, and that's a bummer for the programmer and also execution speed.

My point is on topic because this thread is about C performance, and I've brought up the point that functionality, in this case array indexing arithmetic, defined in the language and implemented in the compiler can be faster than the programmer implementing the functionality in their own code, especially, in the case of strings, if that implementation is via external routines.

I thought that this was all simple and clear.

Re: Why is Rust slightly slower than C?

#144
post #69

Would be nice to also see why Java is slower than C# and Go.

https://www.reddit.com/r/programming/comments/d2pku3/a_highs... > We are at ~20 bytes of allocation per forwarded packet in Java. C# and Go have much better facilities to avoid heap allocations.

Java will eventually get them via Panama and Valhalla projects, something that should have been there from the the get go, though.

Re: Why is Rust slightly slower than C?

#145
post #122
post #118

Earlier quoted context omitted.

I'm also sorry if your exeprience has been similarly hostile. This is not a comment about which languages get used in which shops. Whatever your technology choice you would expect to have to make a case, using evidence, and have that case properly listened to (or why did they hire you?). For performance critical technology you would expect that evidence to include benchmark numbers. Any other approach to considering…

I have not encountered any hostility. But if you don't know how to get better performance from C++ than you can get from C and lots of extra work, you probably will not be hired, most places. It's not about hostility, it's about competence. Some places just demand competence more than others. The laughter would not be about measurable performance; you might well be able to get C code to go as fast. The laughter would…

This conversation is now bordering on unhelpful. C has uses, some of them are compelling. Every finance shop I've worked in uses the linux kernel and drivers extensively. These are (mostly? all?) written in C. As is git. Nobody laughs. C++ has uses. Some of them are compelling. For a given case where these uses dominate nobody laughs. Claiming C is as obsolete as CRT monitors or 10baseT without any supporting evidence? Yeah, no thanks. Someone could take that the wrong way. Actually isn't this what Alexandrescou says about C++ because he's all about D nowadays? What Eckel did when he became all about Java (or is he now all scala?). Last time I saw footage of Stanley Lippman speaking he was being brutally disparaging of C++ and invoking in his defence Richard Gabriel describing C as "a virus" to make him look less hostile in comparison to other language warriors and wars. [2]

It just isn't a meaningful conversation without a specific case, with specific requirements and where a specific solution is advanced with appropriate evidence. If in your experience there has never been a case for C, in your own work in the very broad finance domain, over C++. Great. Your experience differs from mine. I've had circumstance where I've made the case, then implemented and released it and watched the p&l go quite well as a result. I do know how to program in C++ where that is appropriate and indeed I do. No really. Also Java, and Python, and (gasp, even) Perl, and... Like any and every experienced programmer, right?

Claiming someone is "scared of the c++" compiler in the absence of evidence for that is probably not your best comment here. It's actually imho the very worst thing about c++ as a language. That is the casual derogatory, frequently unsubstantiated, statements the pervade the surrounding culture. Linus had something to say about it back in the day [1] so it's not like the C++ folk have an exclusive license on that kind of attitude... His tone there doesn't make me laugh.

Two Cases you might like to consider. (1) Optimising the very last cycle matters, how hard you have to work to shake it out, not so much. Maybe you haven't had that, um, pleasure. (2) You have a reason to want to parse and transform the source. (Given (1) above the reason for doing so might be obvious but I probably shouldn't say too much more about it, also you might laugh! ;-)

[1] http://harmful.cat-v.org/software/c++/linus [2] https://www.youtube.com/watch?v=SLLOSAm-OS0

Re: Why is Rust slightly slower than C?

#146

Earlier quoted context omitted.

I know, the meaning of "zero cost abstraction" is really "zero cost to not use the abstraction." But that's like saying if you don't use rust you don't pay for it. Just because there is the unsafe escape hatch in the language, you don't get to label the language as zero cost abstraction. Because practically speaking there is a lot more runtime cost to rust than people will tell you. Many langauges (almost anything wi…

You still seem to be missing the point. If you use a Rust construct that does bounds-checked accesses, you're explicitly using bounds checks. You're not paying for anything beyond the bounds checks that you're using. If you use a Rust construct that elides the bounds checks (e.g. get_unchecked), there are no bounds checks, and you don't pay any cost for the fact that Rust supports a bounds-checked subscript operator.…

What part of my comment made you think I didn't understand that?

Was it when I wrote: "it really [is] zero cost to not use the abstraction"? Or when I wrote: "if you don't use rust you don't pay for it"?

I understand the concept fine. It is rust's marketing gimmick and not a useful tool to describe the language.

Rust is no more "zero cost" than C++, Fortran, Ada, Objective C, and even D can even make the claim to some extent (you can opt out of the GC and use malloc/free directly). I'm there are plenty more I'm missing. If you use the Java GC that doesn't collect (used for real-time programs), even that probably fits the description.

Under your description an opt in generational GC is zero cost. You can't have the vector be checked, (along with other small performance issues), but use the excuse that you can write code in a way that doesn't use checked access or have that feature's cost. I can do that in a lot of languages.

Also to some extent you should take the ecosystem into consideration where a large chunk of it goes to lengths to not use unsafe such as using a vector for homogeneous objects to get around pointer semantics. That incurs a huge cost, and that should be counted against the language because it makes the other ways too difficult or the main libraries used rely on those techniques. (and if you don't count rust's ersatz standard library, the you can't count Java's standard library since you can always write Java code that doesn't use a GC or extra features - I've done it a few times).

I saw so much promise in rust, but is seems to have gone to complete crap.

Re: Why is Rust slightly slower than C?

#147

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…

> only 2% - 10%

yeah, I wonder in which world they live. If I could sell a limb to get 10% more audio plug-ins in my DAW, you could be sure that my bedtime book would be "Life pro-tips for quadruple amputees"

Re: Why is Rust slightly slower than C?

#148
post #31

Earlier quoted context omitted.

>I wonder if some of the bounds checks could be eliminated by using iterators instead of loops It can and often is. Don't use [] to index into data if you can afford not to. Anecdotally, rustc is also much better at generating SIMD-friendly code with iterators than idiomatic C/C++, but that depends largely on what you're doing.

As an aside, I seem to recall .NET making an interesting optimisation here, such that if you access an array using, for example, `data[20]`, bounds checks are omitted for lower indexes.

There's a similar pattern in rust:

    fn loop(a: &[u8]) {
        assert!(a.len >= 20);
        for x in (0..20) {
            let y = a[i];
            //Do something with y
        }
    }
Adding the assert before the loop will remove the bounds checks happening on each iteration.

Re: Why is Rust slightly slower than C?

#149
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…

”even though C++ suffers from the same aliasing flaws C has.” C no longer has them. Not since a standard that’s 20 years old (C99). restrict qualifier handles that. Unfortunately C++ committee has not included restrict in C++, but it is available in all major compilers as an extension.

C absolutely has them, you can opt out of aliasing on an individual basis but aliasing flaws are the default.

So much so that rustc regularly has to disable their noalias annotations because its pervasive noaliasing exercises rarely used LLVM paths and leads to miscompilation. Outputting noalias is currently disabled again in IR generation[0][1].

Note from downthread comments in [1] that it's completely possible to create valid C code which miscompiles on both GCC and LLVM (though GCC has been fixed since), it's just unlikely that a regular C dev would write the mix of unrolled loops, inlined functions and restrict annotations which triggers the issue.

[0] https://github.com/rust-lang/rust/issues/54462

[1] https://github.com/rust-lang/rust/issues/54878

Re: Why is Rust slightly slower than C?

#150
post #84

Earlier quoted context omitted.

Soooo, those C compilers cheat on the language as defined in K&R etc.!!! WOW!! With that cheating, C gets to catch up with, say, what PL/I was doing with string manipulations in, say, 1969!!! So, this is the 50th anniversary!! C string handling is right up to date as of 50 years ago!!! There is still the issue of a C programmer having to calculate array indices that Fortran and PL/I can do back, way back there, 50+ y…

It doesn't "cheat"; the semantics of the C standard library are just as much a part of the language as the rest. And GCC at least (don't know about the others, not that this isn't true for them) has done this for decades at this point as well. Edit: Before that point, the targets that C tended focus on preferred these operations being in functions anyway.

> It doesn't "cheat"; the semantics of the C standard library are just as much a part of the language as the rest.

As I read K&R, strcpy, etc., where there, in a library of external functions, as a convenience and optional for the user, and NOT part of the definition of the C language. Your YMMV.

The situation definitely is "cheating": In K&R, strcpy is clearly, syntax, semantics, original implementation, an external library function. K&R has the definition of the language. One of the most important parts of C is that it doesn't change. It was clear in K&R that strcpy could be implemented by any user in their own external code.

So, a compiler that implements strcpy with its own in-line, not with external names, code is cheating on the language definition.

C as in K&R was designed to run in a DEC computer with 8 KB of main memory. So, the K&R definition of C was primitive.

Since strings in C as in K&R are so primitive, really a disaster, a situation well understood when K&R was written, some programmers might have done a much better string implementation via external function calls. So, given some old C code, they could have linked in their own external calls not mentioned in K&R and for parts of the old code that called strcpy linked in their own version of that function that worked with the new string functionality. All to have been expected.

So, some compiler writers have gotten more performance from C by cheating some on the language and put in compiler options to justify the cheating.

With this cheating, the compiler writers are making my main point: Functionality defined in the language and implemented in the compiler via in-line code can be faster than functionality implemented in external function calls. That is, the more recent C compiler writers so strongly agreed with this point that they cheated on the language definition to get the gains. This point was made very clearly by IBM as they pointed out that the string functionality in the PL/I language and the IBM compilers was faster than the many Fortran string packages implemented by external functions.

Being faster than K&R style C is easy. So, here I was struck by the point that Rust is not always a LOT faster than C, that is, K&R C. But, maybe Rust IS a lot faster than C with a compiler that does no cheating!

Post reply on HN