Live data from Hacker News

Why is Rust slightly slower than C?

github.com

221–230 of 251 posts

Re: Why is Rust slightly slower than C?

#221

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.

We all know the acronym stands for "Resource Allocation Is Initialization" - and that in the real world the two often have no reason to be semantically coupled. IOW lots of optimization patterns involve decoupling initialization from allocation and the RAII meme encourages programmers to codify the coupling because C++'s shortcomings make it attractive.

That is what RAII stands for, but in practice good use of C++ RAII is all about explicitly separating interface, allocation, and ownership, such that you only pay for as much initialization as you need when you need it.

This takes great care which takes time and leads to slow development. I think of C++ as worth it when this level of care is necessary to create a well-performing system.

I would agree that most toy examples don't do a good job of explaining how to use RAII in a careful high performing way

Re: Why is Rust slightly slower than C?

#222

Earlier quoted context omitted.

Anyone asking for "source" should be able to prove that they've not searched first. Because it's right there. As noted in the other comment it's in the literal documentation for rust. Low effort commenting is usually shunned here, yet the ever prevalent "source?" seems to get a free pass all the time. Really people should say: "source? Because I tried https://www.google.com/search?q=rustc+is+also+much+better+at... an…

Well I mostly agree when the first Google result answer the claim. I've clicked on most links from your Google query and was not able to find something that prove Anecdotally, rustc is also much better at generating SIMD-friendly code with iterators than idiomatic C/C++ Most of the links are about explicit SIMD, something that is off topic with the initial claim and something that c/c++ do far better (so many SIMD li…

Sorry for the confusion. "Anecdotally" as in it's a personal anecdote, I've seen it in my own code.

Re: Why is Rust slightly slower than C?

#223

Earlier quoted context omitted.

I love C, and have written tons of C++: What the parent is saying is essentially right. C++'s compile time polymorphism and lamdas can allow faster than C given the right subset of language chosen. For instance std::sort regularly outperforms qsort(3).

> given the right subset of language chosen Yes, if by that you mean "idiomatic C++ as C++ programmers write it". It's the inexperienced "C/C++" (no such thing, BTW) that are 'choosing subsets', and doing it wrong 90% of the time.

> It's the inexperienced "C/C++" (no such thing, BTW) that are 'choosing subsets'

That's blatantly not true. Strousup himself contributed to the joint strike fighter C++ coding standard which has things like "Allocation/deallocation from/to the free store (heap) shall not occur after initialization." which means that the STL is off the table for example.

Beyond that, there's pieces like RTTI/dynamic_cast that should be avoided for a lot of reasons, perf being one of them.

Re: Why is Rust slightly slower than C?

#224
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 no longer of any benefit, but for the sake of you and your co-workers... Saying that C is predictably inferior, more expensive, and less maintainable shows a blatant amount of incompetence on how either languages operate. C++ only offers abstractions to (debatably) more easily allow for an object oriented design for codebases. Semantically everything that you can do in C++, you can do in C.

There are plenty of features in C++ that are beneficial, particularly the handful of mechanisms that allow you to move away from #defines, but to compare performance between C and C++ simply shows ignorance.

Re: Why is Rust slightly slower than C?

#225
post #160

Earlier quoted context omitted.

This is taking zero-cost abstraction to the extreme, and I think waters down the concept to the point that it almost isn't useful. One can argue that any feature is a zero-cost abstraction for the exact set of trade-offs it has (in the limit: "you couldn't implement a feature that executes this exact sequence of instructions 'mov ...' any better if you did it by hand"). I think focusing on a hypothetical perfect code…

Bounds checking is not an abstraction. Therefore you are the one who is twisting the word "zero-cost abstraction" to cover things it doesn't cover.

Hm, I'm not sure I understand. I don't think I was the one to call bounds checking an abstraction in this thread.

Re: Why is Rust slightly slower than C?

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

The explanation I heard from a Rust core dev (explain why Rust tends to be slightly slower than C++) is the borrow checker makes programmers to use a slightly different coding style. Were C programmers tend to pass references around Rust programmers tend to take copies of to avoid the borrow checker.

Passing the smaller reference will be faster in single threaded code. In multi threaded code I'd expect making a thread local copy to be a win, and indeed multi threaded Rust programs tend to be quicker than their C/C++ counterparts.

Re: Why is Rust slightly slower than C?

#227
post #112

Earlier quoted context omitted.

> In the finance world, you would be laughed out of the room for proposing C for a performance-critical task. This has not been my experience and I'm greatly relieved that I haven't been subjected to such a hostile and destructive working environment in finance as yourself. The correct response is always: "Show the benchmark numbers and make your case that the trade off is worth it." Then there is discussion on how c…

> The correct response is always: "Show the benchmark numbers and make your case that the trade off is worth it." Then there is discussion on how compelling a case has been made. Where do you work that allows you to implement everything twice, once in C and once in C++, for a proper comparison to be made? (I realize that's not quite what you said, but if we're going with 'benchmark', then presumably those places have…

As an example, usually there is a default C++ implementation because C++ makes things easier for the programmer so it makes sense if you're at the end of the food chain that requires perfomance (ie you're not using a memory managed language in the first place because that's easier still). So then you benchmark it thorougly. Get stuck into all the perf numbers and analysing those. You note why you think you can shave X off because the latency is due to i, j and k measures that look as though they could be improved so that's probably worth a go. Now you can (at least sometimes) in your lab, replace one part with (say in this example, C code) and see if your perf stat ratios improve the way you think they should. Yes it is difficult. Yes there are plenty of times where you see nothing because the slow from the code you changed is actually manifesting in cache misses elsewhere.

Micro benchmarks sadly have a way of showing nothing much at that end of things. Showing it's no worse/better doesn't even mean it's no worse if the additional/reduced pressure on caches doesn't result in much in the way of additional/reduced cache spills. So you end up doing mirco optimisations that each, taken alone don't do much. But when you get them all together you cross a threshold that has a considerable improvement. I believe SQLite did something like this although probably in a more restrained fashion as they have other goals than being the lowest latency solution against similarly motivated competitors.

Then of course at some point you get a reputation for success so you show the problem and the numbers identifying it and just say "I want to invest X of my time trying Y which I believe has a reasonable chance of helping" And you are told to focus on that and please let them know if you have any more good news. ;-) Sometimes your ideas are genuinely a wash and not worth merging but it is noted that it was worth trying and you're thanked for your efforts.

As somebody else noted in this thread the game has moved beyond much of this kind of thing in some, possibly many instances.

Re: Why is Rust slightly slower than C?

#228
post #118

Earlier quoted context omitted.

Having spent 15 years in finance, I've never seen C used for perfomance critical code. It's always been C++. Some shops use Java or C# with GC effectively disabled, but those are rare. If you can preallocate all of the memory you need, this may be fine, but not all trading systems have that luxury.

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 didn't say there was hostility towards one tech stack or another, I was just stating my observations/experience. In my experience, once a firm has one or two tech stacks, they don't really want to deviate too far from what's entrenched because, well, they need to have the talent on hand to support everything. This becomes exponentially harder if every developer chooses their language/framework of choice. Generally, though, if there's a compelling reason to break from the core competencies of the firm, exceptions may be granted (this was how Python first got its foothold in my first firm - I could easily, e.g. generate, Python wrappers over my C++ APIs that allowed me to do everything my business users wanted while still maintaining compliance control and audits over data changes).

Typically, you can usually tell the age of the trading firm by the tech stack. Older companies are usually on C++ and have millions upon millions of existing legacy code that works, so there's little impetus to rewrite in the latest shiny. Younger firms are more likely to have embraced Java and younger yet, C#. This doesn't always hold true, though, it's just a generalization of my experience.

In my 15 years in finance, I spent 9 years at my first firm, and when I joined it was purely C++, with some perl to move data around between vendors and systems. There had been some Java, but we had a bad interaction with Sun Microsystems (at the time) and our CEO came down hard and kicked Java to the curb (and we migrated off of Sun/Solaris onto Intel x86 & Linx & C++). Towards the last several years I was at that shop, C#/WPF had been embraced for all new UI work, and even some rewrites of existing MFC apps were in progress. Python had also largely replaced Perl for all new scripting/data munging and had also been embraced by the quants. All of the servers still ran on Linux and were in C++ when I left ~6 years ago. There was even talk of migrating from Sybase on Linux to MS SQL Server. That didn't happen in my time, but from former colleagues I've kept in touch with, they've pushed forward on that. I don't know if they're using SQL Server on Windows or on Linux, now that that's an option.

My current shop is the oldest shop I've ever worked for (founded in the 70s) and is entirely a Windows/C# shop. They brought me on this year to help with their build out of Python at the firm (mostly for our quants). I'm actually really enjoying this position, because they're new to Python, but I've got +15 years experience with it, there's a lot of greenfield development and next to no existing legacy code, so I largely get to drive style and architecture.

Re: Why is Rust slightly slower than C?

#229

Earlier quoted context omitted.

Bounds-checked indexing isn't an abstraction, it's a safety feature. The abstraction is compared to manually doing bounds checks like you would in C. // C safe subscript if (i That's the abstraction, and Rust introduces no overhead here.

This is such a useless definition of "zero-cost" abstraction that almost everything qualifies for it.

It's literally the definition. And very little qualifies. An abstraction is zero-cost if there's no runtime penalty, including if the code you'd write by hand to accomplish this goal is no better than what the compiler synthesized for you via the abstraction.

If the use of the abstraction forces your data model into a suboptimal representation, it's not zero-cost. If the compiler emits code that's worse than the straightforward manual implementation, it's not zero-cost. If the emitted code involves runtime checks that aren't necessary without the abstraction, it's not zero-cost.

For example, reference-counting is an abstraction over tracking the lifetime of your object. In some cases (where ownership isn't clear) the retain count introduced by reference counting is required and therefore not a cost, but in most cases the point at which the object ends up freed is actually predictable, and therefore the cost of all the reference counting is something that would have been avoided without the abstraction. Therefore, reference-counting as a replacement for manual alloc/free is generally not zero-cost.

Or how about iteration. Rust has an external iterator model (where you construct an iterator and run that, rather than passing a callback to the collection). In most languages an external iterator model is a non-zero cost, because you need to construct the iterator object and work with that, which is a bit of overhead compared to what the collection could do with an internal iterator model. In Rust, external iterators are frequently zero-cost because they usually get inlined. So you can write a high-level loop that includes a filter and map and the end result is very frequently just as good as (if not better than) what you'd have done if you wrote the iteration/filter/map by hand without Rust's iterator abstraction.

Re: Why is Rust slightly slower than C?

#230
post #160

Earlier quoted context omitted.

This is taking zero-cost abstraction to the extreme, and I think waters down the concept to the point that it almost isn't useful. One can argue that any feature is a zero-cost abstraction for the exact set of trade-offs it has (in the limit: "you couldn't implement a feature that executes this exact sequence of instructions 'mov ...' any better if you did it by hand"). I think focusing on a hypothetical perfect code…

Maybe! I think that the concept is a bit more focused than most people think it is. I can appreciate this perspective though. It's a fuzzy concept, so there's decent room to poke and prod around the edges :)

Yeah, that's fair. I think there's a strong argument that bounds checking satisfies the "don't pay for what you don't use" rule (although one could say that every slicing having to carry around its length, doubling it's size, is a pervasive cost, but that's fairly weak, given the other things it enables), but I think the other rule is much, much less clear.
Post reply on HN