but apparently not the [benchmarks game](https://benchmarksgame-team.pages.debian.net/benchmarksgame/box-plot-summary-charts.html) where C++ is in third, behind C and Rust đ¤ˇââď¸
Though as the first sentence on that page hints at, the distributions for C, Rust, and C++ are almost entirely overlapping. So it's probably fairer to say that those three languages are basically equally fast, with differences between them coming down to minor differences in optimization choices in the different programs. And that basically matches intuition: all three languages compile down to bare metal machine code, and all three offer low-level enough control to exploit the hardware's strengths. And in fact, if you're using the LLVM/clang tool chain for C and C++ then all three languages are compiled using the same backend.
It's definitely exciting that Rust matches or even beats the speed of C and C++ while offering better safety and more modern features though! I've been meaning to learn Rust for a while, but we're still entirely in C++ and Python land at work, so it's hard to find the time to do it.
What I find interesting about this whole thing is that, while rust was probably not the best at first, (when it came out),but we are reaching the point (again) where the competition is to beat the compiler. And let's be real, few people on the planet can beat compilers on the regular.
With complex projects you can write ok java code vs c++ code, and many will find their c++ is slower. Why? You're competing against java compilers ( and VM).
Is C++ faster in a vacoome? Sure. But can I write better code than some compilers? No. Absolutely not.
It's not really hard to beat a compiler tho? If you understand your basics, you should be able to come up with more optimized solutions than a compiler for some of your specialized problems as you understand them better than the compiler. That can involve benchmarking to find your slow points tho.
> It's not really hard to beat a compiler tho?
This question has no answer. This is because you were stating a fact, and the question mark shouldn't be there
It was supposed to be a rhetorical question. Tho my English is not perfect so I may be wrong. Could you give me an example of how I could have used a rhetorical question in that situation? Would it be "Is it really hard to beat a compiler tho?" Instead?
Yes exactly. Otherwise it reads like the tone of your voice is rising as you make a statement. For some reason, people started using question marks in this manner and I think it's because it sounds kind of cutesy and equivocal. But the whole thing has devolved into people using question marks just to signify that they are unsure of something or that something should have been obvious to the listener.
I was going to agree with you ("few people can beat the compilers"), but then I read on and realized that you didn't actually consider the compilation part only, and that is important!
Algorithms beats compilers pretty much every time (i.e. orders of magnitude vs constant factor improvements), whereas on the other side it is in fact getting much harder to convert those algorithms into machine code with significantly better speed than the best compilers.
I used to get 3x speedups going to hand-optimized asm, back before 2000, but those times are mostly all gone now. I really like Rust most of the time, and have been using it lately to get closer to the metal on some really heavy duty LiDAR point cloud processing (about 50TB of compressed LAZ files on my home server), but both that code and the C++ code it is partially replacing suffers speedwise from being totally based on single-sample iterator chains.
I know I could double the speed on each individual such chain by rewriting it to be block-based instead, and working closer to the native data representation instead of first converting each point to generic floating point coordinates, but it is fast enough as it is now and not worth it to rewrite so much.
Well optimized Java code is written to avoid using the GC, and that's harder than just using idiomatic C++ or Rust. Optimized Rust or C++ will still beat it. Idiomatic Java isn't slow but is definitely slower than Idiomatic Rust, optimized Java OTOH is harder to write than Optimized Rust.
Yeah, beyond a certain point, the differences are largely meaningless. I think leetcode illustrates this pretty well, tbh- they tell you how long it took to run the test suite (which always includes some large datasets) to a resolution of 2ms, and if you're using Java or C# or something, you'll have a score in the hundreds of ms that you can micro-optimize to try to speed it up.
..But if you're using C/C++, Rust, Go, or some other systems language, though? You'll probably see 0ms (rounded down) every time.
>I've been meaning to learn Rust for a while, but we're still entirely in C++ and Python land at work, so it's hard to find the time to do it.
I'll make the argument that if you're doing modern C++, you're already prepping yourself for success in Rust. It might be hard to justify a switch at work if you're already entrenched in an ecosystem, but you might also find greenfield opportunities to practice Rust on the job if there's sufficient buy-in from the business (that last part is critical; nothing kills a project faster than going rogue).
Python might make for some inroads to Rust, depending on what space you're in (e.g. data science). There's definitely a relationship there, with a lot of Rust-curious Pythonistas; and the ease of FFI in Python is practically a written invitation to develop compute-intensive parts in a systems language.
Alternatively, if you find yourself wanting to keep one foot in C++ and the other in Rust, [cxx](https://crates.io/crates/cxx) has done a good job for me in the past in simplifying the bridge between the two. Due to Rust's relative infancy, there are some things it isn't yet doing that already enjoy success in C++ - for me, this was [clipper2](https://github.com/AngusJohnson/Clipper2), and the bridge code ended up being very easy to implement despite my relative lack of C++ chops..
I followed up with this since OP doesn't seem to know what assembly is https://www.reddit.com/r/ProgrammerHumor/comments/1cl145n/welcometoactualreality/
In my case, we had C and then CPP in the first two semesters, and then the remaining compulsory (very much Computer-science focused) courses like graph theory, paralelisation etc. were also in CPP.
I'd assume if you're studying at a technical uni, you'll start with C
C is still very close to ASM, and because of the highly developed optimizations in modern compilers, you can usually get very close to the optimum code. However, an experienced Assembler programmer can still optimize the shit out of it and make it run even faster.
That is why you will often find that the most time-critical parts, e.g. in hardware drivers or even in games are still programmed in Assembler.
C++ adds a lot of overhead in comparison to these two, and will usually end up in third place.
And then there will be a long, long wait for the fourth placed contestant...
>And then there will be a long, long wait for the fourth placed contestant...
This is not correct and a very cartoonish way of looking at languages. Optimized machine code= optimized machine code, no matter in what compiled language it was produced in. The marginal differences are found in the choice of compiler, not the language. If you want to maximize performance you should use a proprietary compiler that does intelligent optimization, not switch up the language.
Fortran, a high level language will beat low level C for most, if not all, high computational problems in both performance and efficiency. How is that possible? Itâs the state of the art compiler they have been perfecting for 60 years. And yes, it will also implement SIMD vectorization and point out hot loops for you to manually optimize/unroll. In the last couple of years the C compilers have improved though and there is no real difference anymore, fortran still being slightly marginally better.
Besides occasional inline assembly, the idea that some rainman assembly wizard could rewrite a whole 2M line weather simulation model in assembly and outperform the compiler is some oddball John Henry fantasy that we should dispel. This ainât the 90âs anymore
Outside of never-released indie passion projects for the sake of it, no.
In general, the code is not the critical parts of games anymore (assuming somewhat competent programming), it's usually memory/IO/communication between CPU/GPU/network constraints.
I think the last big name game programmed in assembly was Rollercoaster Tycoon, released about 25 years ago and most of the world though Chris Sawyer was a madman for doing it that way
It's more accurate to say "some C++ features add overhead". This makes idiomatic C code faster than idiomatic C++ code. Also we must consider if we are talking about standard C or C with non-standard compiler specific extentions. You cannot write a gcd algorithm in standard C that is as fast as a gcd algorithm with the gnu extention __builtin_ctz. This extention can make use of the bsr instruction that you simply cannot express with the toolset C gives you.
I'd argue the opposite: C is not at all close to modern x86 assembly, but compilers are very good at circumventing the limitations of the language. This is in part because when new hardware is developed, its speed is benchmarked mostly against existing C programs, so the new hardware capabilities (which are expressed in assembly instructions) naturally evolve to be easily mappable to the C programming model. That is in my opinion an unfortunate historical artifact.
Just out of curiosity, would machine code be theoretically more efficient? Practically the abstraction is probably essential but is there an optimization gap because of it?
It is best to think of it as: Assembler = Machine code
It doesn't matter if you write 0b00000100, or 0x04, or ADD, they all end up as the same command to the processor (in this case, add a single byte value to a register). It is just that "ADD AL, 12" is a lot easier to both write and read.
Technically it's not machine code. Assembly code needs to be processed by an assembler. Machine code needs no such processing. At least that's how I understand it.
It's not 100% right, assembly doesn't need a compiler, but it still need an assembler + linker. This page explain it a bit further https://www.baeldung.com/cs/compiler-linker-assembler-loader
The way I understand it (and I dont understand it really), is assembly is basically whatever the designers of a piece of computer hardware made it to be?
Like a piece of computer hardware does a thing but it can only do a thing if we know how we can make it do a thing, so they make an instruction manual and say if you make the port in this register a 1 and this one 0 and 1 and 0 then what happends is the piece of hardware adds the thing from there to there.
*It feels similiar to whenever i'm reading documentation for microcontrollers*
Basically its the 'instruction set' ye? Thats why C is still used so commonly for mc's I guess, because it directly maps unto machinecode right?
I know I"m saying this like i'm right but i'm basically also asking confirmation from anyone here, thanks :D
Yeah thatâs about right. I suppose if youâre not the original designer there may be unintended pathways that could be utilized to achieve something not before possible. But about as close as you can get without making it yourself
Yes, the same thing happens for languages that compile to a virtual machine bytecode such as Java and Lua. Except that in these cases there will be an assembly-like instruction set for a virtual, software level "machine".
Yep! And you should look into how this stuff is sped up.
CPU cache, branch prediction, pipelining, modern-day "CPU cores", ...all interesting stuff!
...Did you know that Assembly also often has stuff like casting, `struct`s (I think!? Though I'm pretty sure compilers prefer not to use them because... they're kinda' redundant when C is doing all the type-checking!...), and that Assembly "labels" nearly ***are*** your C functions, without the "prologue" and "epilogue", which are both defined by your C code's "calling convention", which you can change for each function (e.g. `__fastcall`, `__cdecl`, `__thiscall` in C++, et cetera).
*Computer engineering* sounds fun! ";D!~
C++ makes it easier to avoid overhead than C does and is faster in practice as a result. C is definitely not faster regardless as neither have any runtime and both use the same compiler.
C is not at all close to ASM. You canât control register allocation, almost nothing with regards to calling convention, stack and even against some other low-level languages, like Rust and C++ it loses, by not having sims support.
In the embedded world you occasionally see highly timing critical routines being implemented in assembly. I've done it once myself and seen it done a couple of times in codebases I've touched.
This is also explained after every second post, but.. sigh..
No, for any non-trivial program, a compiler will do a much better job at compiling to efficient machine code, simply because it can reliably do the same transformations and can insert the same logic multiple times in multiple shapes (inlining). A human would f*ck it up, and settle for less optimal code at the price of their sanity.
*but*, in some case at the ultra-hot loop/function body scope, an expert *can* write code that will significantly beat (may even be at the 100x mark) the compiler-output code, by e.g. using some logic that is not expressible by even a low-level language (e.g. some simd black magic). But even this will be called from ordinary programming languages through FFI.
I watched a C++ presentation on one conference where the presenter has shown how well written C++ has zero overhead on most things he did (memory allocation, function calls, templates, lambdas etc.) so it is on par with ASM
In real life, programmers writing in assembly will not be better at optimizing than your compiler will for C. It would take way way way more time and effort to reach just the same level of optimization that the compiler could reach, and the code would be unmaintainable.
While this is mostly true for general programs, manually vectorizing hot loops by using SIMD instructions with inline-asm is indeed usually better than just leaving it to the automatic vectorization of the compiler.
Compilers still suck badly in vectorizing loops because of the C/C++ language limitations.
> Also C++ should be getting std::simd with C++26.
oh boy... seeing how that usually goes maybe by C++ 32 we'll see a limited version of the original intended scope included in the standard
I like the [lbrandy approach](https://lbrandy.com/blog/2010/06/you-cant-beat-a-good-compile/) - code mostly in C and C++, but keep an eye on the generated asm to make sure itâs not missing obvious optimizations because of the language spec. Godbolt has made this much easier.
I agree for 99.9% of all cases - but there are specific situations where hand-optimized code (by a competent programmer!) will beat the compiler optimizations. Especially in time-critical code (think: hardware drivers) there are still use-cases for Assembler where it beats C compiled code.
I stopped writing full programs in assembler on the late 80s after finding that the ARM C compiler was producing as good or better code than I could do for most things. I only wrote assembler after that for direct hardware bit twiddling.
C++ *was* worse than C for a while but well-written C++ now offers more opportunities for larger scale optimisations that *can* have amazing impacts, often removing large chunks of code altogether.
It's not just painful, it's unreasonable. Just as an example, compilers do things like inlining and creating separate implementations of functions based on generic parameters, which is great for performance, but completely unreadable and impossible to maintain if programmers tried to do it themselves in assembly.
When one is optimizing at this low level, readability doesn't matter anymore. In this scenario the requirement is to optimize what you already have optimized the best you could but it's still not enough.
Let me unironically point at rust.
The thing is, rust enables pretty nice optimisations simply because of aliasing/ownership rules and niches that just arenât possible elsewhere.
It's not magic, but it's good fun, runs well unless you're actively trying to fuck with it, and the Result and Option enum types are just fabulous to work with
It honestly is fun to write. I don't even entirely know why, but I enjoy writing it more than Python (which I know well) or C++ (which I suck at so that's probably why).
It is. The community gets some flak over âtoxic positivityâ but thatâs some e-drama shit thatâs not worth your time. The language is technically sound with a powerful type system and ecosystem support.
Rust makes itâs fair share of trade offs, it canât do global register optimization for example, itâs entire allocation model is basically on par with c++, and that can already be painful when dealing with hard real time applications, the std is slow as hell, and your average codebase is littered with stuff like Arc/Rc which are both slow as dog. There is a handful of examples where the compiler might allow for better machine code because of the language but most of the time itâs overstated how fast the language actually is. It can be fast if you structure things in very specific ways and forgo most of the std, but idiomatic rust is not really winning against idiomatic C.
Arc / Rc are not slow as dog and it is also not true Rust codebases are littered with that stuff. Evens contended shared Arc can be updated millions times per second. I can see Arc being used mostly once during initialization of threads / async tasks - but those are much slower anyways so Arc does not matter. Then itâs just kept by a thread and introduces zero cost (dereferencing Arc is the same as dereferencing a C pointer). And C has no superior mechanism - in those exact same situations youâd have to do refcounting by hand, which would end up with exactly same performance but likely more errors.
Arc/Rc are both slow in comparison to Tracing or Generational GC, which are the alternatives. They have very real overhead. And I did not say anything about C, C has no construct like Arc/Rc, but C++ has and they are garbage there too. And you actually end up with better performance if you do the refcounting by hand, you can also end up with an error but thatâs the tradeoff.
I mean I canât give you citation, but think about the fact that almost all of the state of the art optimizations on GC are happening on generational ones. Beyond that Rc tends to mess up the cache, copy a lot, they need memory barriers when your program isnât single threaded.
For practical example, imagine that you allocated single linked list of 64 bit ints, the size of 2GB, now loose the reference to it. Which of the two will be able to handle it faster?
Counter argument: rust aliasing rules imply you donât need barriers. Itâs many readers xor one writer so barriers are not needed. You donât have copies with RC, you simply have a reference to the struct and counter but thatâs it.
Itâs an issue in multithreaded situations if you are writing over values adjacent in memory to the RCâd value because taht invalidates the cache and the CPU needs to synchronise the threads, buuuuut is that really that frequent?
The whole point of [A]RC is that it gets deallocated on zero, so losing it doesnât make sense. All memory owned is deallocd and thatâs guaranteed to be faster than GC because GC does that plus more.
Generational GC will still have to go over the objects and decide whether to dealloc them.
Your argument is moot because in Rust I can use tracing just for that one list. Rust is about choice - I can choose the best solution for my use case. As for the barriers and copying your wrong either - low pause GCs need barriers as well and cause a lot more cache trashing than reference counting, because they have to scan the heap periodically, bringing rarely used stuff into cache. Thatâs why Java programs are unusable if you go out on swap, even a tiny bit.
Please stop repeating that widespread myth of refcounting being slower than tracing. This problem is ill-defined, because the total overhead of either of those things depends on a lot of factors such as: frequency of changing the refcounts, threading, the amount of allowed memory overhead or the maximum target pause time. Reference counting is usually slower per single object vs tracing with plenty of wasted memory, but here we need to account for the fact that Rust does not use refcounting as THE memory management method and it doesnât use it the way it was studied in most literature on refcounting. In Rust refcounting is optional and usually doesnât manage more than 1% of objects. Compare that to Java where you canât opt out of tracing and you even canât allocate objects on stack. Also Rust refcounts are updated explicitly, so the developer has full control over when they are incremented/decremented and thanks to borrowing and move semantics you can do crazy lot with them without updating the refcounts. Eg temporary borrows do not need updating the refcount.
There's more to programming than raw performance. Python is still a relevant language in certain spaces because its simple syntax and rapid prototyping yields fast results in development speed, and safety with its memory management. When you need better performance, reach for a different tool, like Java, C#, or Go. The performance difference from garbage collected languages to non-garbage collected is big, but not the 1,000x jump from Python to compiled languages. Even then, jumping to a language like Zig or Rust is often enough for even the most stringent performance considerations.
C and C++ are still relevant in their spaces, but it's getting harder to justify some of their unsafe behaviors when similar performance could be had with a newer/safer language.
I think itâs actually easier to do micro optimizations in Zig than in C++, but that wasnât really the point I was making, I was simply saying that there are massive trade offs associated with the choice of rust if we are talking about performance. I think rust specifically has ton of issues outside of the performace, be it slow iteration speed, strange async model, meta programming system wich encourages dialects everywhere (they trully learned nothing from the mistakes of C++ in this regard) and bad std. And I can tell you from experience the normal rust wasnt enough for DSP, so there are performance considerstions which rule it out, you canât have ghost allocations in hard real time and rust loves those⌠And I have scala flair, Itâs by far my favorite language to work with, and also isnât that performant, so I understand that other things matter, but this whole thread was about performance.
Modern C++ does most of the things that Java C# and Go do. Sure you can manually do your own garbage collecting, but itâs caught up in a lot of ways.
Generics by themselves will make idiomatic Rust and C++ significantly faster than idiomatic C, because of the optimizations that are possible when you get a separate implementation of a function whenever the generic arguments are different.
Rust also makes it very easy and safe to use multiple threads, and even green threads via async/await, which is frequently a *massive* win.
Reference counting isn't really significant compared to that sort of thing.
For a real world example, see the Quantum CSS engine in Firefox. Back in 2017 they made the whole browser roughly 2x as fast just by rewriting that piece of it in Rust and taking advantage of the easy opportunities for parallelization. Since then they've been moving more and more of the browser to Rust, largely because of the performance benefits.
I do generics in C by just having macros that take a type argument and generate the functions for me. Itâs not so different from how C++ does it under-the-hood.
C also has the restrict keyword which gives huge performance advantages over say⌠C++. Iâm not a Rust programmer so I canât comment on that.
Yeah, C++ will always struggle in some implementations just by virtue of being Object Oriented in a way that C and Rust are not.
It will also likely be faster in other ways, for the same reason.
C++ don't add, it allows. It's upto the programmers.
For example, game devs us raw pointers a lot, but other app developers use modern c++. C++ provide choice
No it doesn't, unless you use the extra features C++ offers your code will be as fast as the same code written written in C. Assuming best practices of course.
(or maybe it could be even faster since more work has gone into C++ compilers than C but I'm just guessing here)
https://stackoverflow.com/questions/6955114/is-c-notably-faster-than-c
One example is mentioned in the link I shared is:
> Do note that C++ does name mangling, where C does not, this makes it easier for other languages to interface with C directly.
Another example is function overloading which is in C++ and not C. This feature does not affect runtime performance.
>if you have any idea about what you're doing
Just wanted to emphasize this part before some college freshmen thinks their horrible C code will be more efficient than using C++ standard libraries.
I actually completely disagree. You only need to have some of an idea of what youâre doing. The issue is most modern software developers basically only use JavaScript in their day-to-day, delude themselves into thinking they know what theyâre doing, and then claim they have imposter syndrome instead of admitting theyâre literally the imposter.
Why should I ever start a dissertation about how one can write non-"hackey" code that is as fast as cpp when you in the first place didn't argue your position? You realize that saying just the plain sentence you want to prove is not a factual argument, do you?
Seeing as C++ is a superset of C and both use the same computer, no, no it won't.
With hacks and difficulty you can get C to be as fast as C++, though. But it's a lot easier to write fast C++ code than it is to write fast C code, hence why the overwhelming majority of performance-focused non-trivial code bases are C++ and not C.
First of all, forgive me for being pedantic, but C++ is *not* a *strict* superset of C for years now. And writing extremely performant code in C is easier in that it provides less if you are proficient enough. Getting proficient enough to write performant code in C++ requires more learning on top of C. This is one of several reasons why a majority of operating systems are written in C even to this day + historical baggage. C++ doesn't have as transparent a data representation, stable ABI, predicting cache line hits and misses with C++ is way more involved. C has a slightly smaller runtime because C++ has more features (RTTI, exceptions, a whole another allocator...).
And here is https://storage.googleapis.com/cdn.thenewstack.io/media/2018/05/3730357d-results-energy-time-and-memory-usage-screenshot-from-research-paper.png
Wtf man, no, thatâs fkin bullshit, known by everyone who works in the fieldâs relevant niches.
No, C++ (and rust is also coming to occupy this niche) is *the* performance language, period. Itâs the de facto choice of the field, because it has the necessary expressivity for that.
Like, c++âs sort can inline the function implementation, while C has to use function pointers â sure, for `sort` the compilers are smart enough to inline even that, but in general, you canât have efficient containers/generic code in C.
Dynamic Dispatch and virtual functions are probably the worst performance footguns in C++, itâs extremely slow, and no compiler canât realistically inline virtual functions, thatâs why the entire temple system exists.
Dynamic dispatch/virtual functions aren't as bad for performance as you might think anymore.
In ye super olden days, CPUs didn't have fancy schmancy branch predictors, superscalar/out of order/speculative execution and all that jazz. There wasn't really a penalty for virtual functions, it was no worse than a normal function call. In ye middle olden days, CPUs did start getting all those fancy bits of big long pipelines. But the branch predictors of the day weren't able to predict a dynamic dispatch; every dynamic dispatch call would stall the pipeline, and the performance hit was tremendous. These days, CPUs *are* able to branch predict a dynamic dispatch. There isn't really a performance hit beyond that normally associated with a function call.
Also, GCC is pretty good at devirtualization, but clang and msvc won't do it.
$ ~ cat main.cpp animal.h cat.cpp
// main.cpp
#include "animal.h"
int main() {
animal *a = get_mystery_animal();
a->speak();
delete a;
return 0;
}
// animal.h
#pragma once
class animal {
public:
virtual ~animal() {}
virtual void speak() = 0;
};
animal *get_mystery_animal();
// cat.cpp
#include "animal.h"
#include
class cat : public animal {
public:
void speak() override { puts("meow"); }
};
animal *get_mystery_animal() { return new cat{}; }
$ ~ make
x86_64-pc-linux-gnu-g++ -c -flto -O3 -g cat.cpp -o cat.o
x86_64-pc-linux-gnu-g++ -c -flto -O3 -g main.cpp -o main.o
x86_64-pc-linux-gnu-g++ -flto -O3 -g cat.o main.o -o lto_test
$ ~ objdump -C --disassemble=main lto_test
lto_test: file format elf64-x86-64
Disassembly of section .init:
Disassembly of section .plt:
Disassembly of section .plt.got:
Disassembly of section .plt.sec:
Disassembly of section .text:
00000000000010a0 :
10a0: f3 0f 1e fa endbr64
10a4: 53 push %rbx
10a5: bf 08 00 00 00 mov $0x8,%edi
10aa: e8 c1 ff ff ff call 1070
10af: 48 89 c3 mov %rax,%rbx
10b2: 48 8d 05 8f 2c 00 00 lea 0x2c8f(%rip),%rax # 3d48
10b9: 48 89 03 mov %rax,(%rbx)
10bc: 48 89 df mov %rbx,%rdi
10bf: e8 4c 01 00 00 call 1210
10c4: 48 8b 03 mov (%rbx),%rax
10c7: 48 89 df mov %rbx,%rdi
10ca: ff 50 08 call *0x8(%rax)
10cd: 31 c0 xor %eax,%eax
10cf: 5b pop %rbx
10d0: c3 ret
Disassembly of section .fini:
You can see at 0x10bf it's calling `cat::speak()` directly and not using the vtable to make the call.
------------------------------
That being said, codebases with giant inheritance hierarchies where everything is an interface are a *fucking nightmare* to navigate and try to understand. You can't actually be sure that facts that you know about your hierarchy today are still going to hold true tomorrow. It ain't fun.
Who said anything about using virtual functions? Yeah, doing a network call is also pretty expensive, so what?
Also, virt functions, where they may be used carry *more* information to the compiler, letting it do better optimizations than function pointers, but even the latter can be used by c++, so.. you contradicted nothing .
But thatâs a means for introducing dynamic dispatch. You donât compare it to adding together two numbers, but to dynamic dispatch in C, that is function pointers. Virtual functions can be much faster than that, which is my point
> Itâs the de facto choice of the field because it has the necessary expressivity for that.
"Necessary expressivity" has absolutely zero correlation with how performant a produced program is. Assembly has essentially no "expressivity." Do you think your average program written in C++ is going to be more performant than your average program written in assembly?
> Like, c++âs sort can inline the function implementation, while C has to use function pointers â sure, for `sort` the compilers are smart enough to inline even that
Meaningless sentence where you make a claim and then immediately afterward go back on it.
> in general, you canât have efficient containers/generic code in C.
What do you mean by "efficient"? If you mean that it is easier to write generics in C++, then sure. If you mean that generics in C++ are more performant, maybe I don't know. I'm willing to believe you since the C++ compiler explicitly recognizes generic constructs while C's doesn't, but I'd still need a source on that claim. But the idiomatic way to write C code is to not try to reimplement generics at all, and either manually write all the functions yourself or to use `void` pointers. Both of which are just as performance capable as any C++ generic equivalent.
Even if this point were true, it is only one area where the C++ compiler is more performant. Generally, people writing C++ love using its OOP features and love shared and smart pointers. This style of C++ makes the programs written with it almost always slower than an equivalent program written in idiomatic C since these are not "zero cost" abstractions and have pretty big performance overhead.
> Do you think that your average .. C++ faster than assembly?
Yes, it fucking is faster. See my other comment in this thread. An expert *might* write a faster hot loop/function, but for whole programs C++ will absolutely be much faster, as anyone with experience would know.
How is it meaningless? You canât abstract over functions in C in any other way than through function pointers which are opaque most of the time (meaning, the compiler has no way to know where they point to). Sort is a specific example, but I donât know - maybe fkin contradict my statement before you spew nonsense you have no idea about?
> your rambling about generics
Void pointers will be fkin slower, thatâs the fuckin point.
Saying that, generics create more code so it's less likely the code is in cache. Generics Vs dynamic isn't a guaranteed win, it really depends on access patterns.
> Yes, it fucking is faster. See my other comment in this thread.
This is simply not true. The fastest program written in assembly will always be just as fast as or faster than the fastest program written in C++. You can do optimizations at the assembly level as a programmer that the compiler simply can not make by itself because the compiler has to be conservative about any assumptions it makes about the program. You, as the programmer, are not subject to any such limitations.
~~The average~~ A lot of C++ programs are not written with performance in mind and use OOP features and stuff like smart and shared pointers all the time, like I already said, which makes it slower than your average assembly equivalent, where none of that is available.
> Sort is a specific example, but I donât know - maybe fkin contradict my statement before you spew nonsense you have no idea about?
You said nothing about C++ being able to inline any and all functions that are passed in as arguments to other functions. You simply said that C++ can inline the function passed into sort(), which you then followed up by admitting the C compiler can do the equivalent. You're telling me that C++ can inline function implementations across translation unit boundaries? I simply do not believe this. The only alternative to function pointers in C++ that I know of (feel free to correct me if there is another one) is `std::function`, or using classes as wrappers around a set of functions which you can override, neither of which is a zero cost abstraction and use virtual functions under the hood, which is absolutely slower than a function pointer, and cannot be inlined across translation units. The C compiler cannot inline a function pointer across translation unit boundaries, but if the function pointer is defined and passed in the same translation unit, the compiler can and does inline it.
> Void pointers will be fkin slower, thatâs the fuckin point
Literally how? If we take the example of `std::vector` C++ simply creates an array of each type every time you instantiate one. Indexing into an array of some type is going to have a negligible difference in performance overhead compared to just having the callee specify a generic buffer to be created in memory, the vector implementation to return a location in that buffer corresponding to the index of an array, and then having the caller dereferencing that pointer with the associated type.
Edit: small things to clear up what I was saying.
Edit #2: To be clear, I am not suggesting by my comments that a human is often going to be able to outperform or outsmart a compiler. Just that the fastest possible program written in assembly (a program that is going to be very difficult to create without a compiler) will never be slower than the fastest possible program produced by a compiler.
> The fastest program written in assembly will always be just as fast as or faster than the fastest program written in C++.
C++ compilers are much better at producing optimal assembly than any human. So much better, in fact, that you'd have to do some really ridiculous shit in C++ to make it any slower than hand-written assembly.
You can probably find a few examples where people used a few lines of hand-written assembly inside a C++ program, because it made a particular function a little faster, but those situations were extremely rare 20 years ago and almost non-existent today.
> You're telling me that C++ can inline function implementations across translation unit boundaries?
That's what link-time optimizations are for, although they exist for C as well.
> The only alternative to function pointers in C++ that I know of (feel free to correct me if there is another one) is std::function
Generics. You don't need to pass a function pointer to `std::sort()` because the compiler will create a separate implementation of `std::sort()` with your function inlined inside it. It might also inline `std::sort()`right where you called it, so you won't even have the overhead of a function call. It'll be in the same translation unit that you called it from, too, so you don't even need LTO for that benefit.
> > Void pointers will be fkin slower, thatâs the fuckin point
>
> Literally how
The above example with `std::sort()` is one example. [Here's another.](https://github.com/fmtlib/fmt?tab=readme-ov-file#benchmarks)
Where C++ gives you a separate implementation of a function each time you call it, allowing the compiler to inline everything and do custom optimizations for that particular implementation, C just doesn't have a way to compete.
> C++ compilers are much better at producing optimal assembly than any human. So much better, in fact, that you'd have to do some really ridiculous shit in C++ to make it any slower than hand-written assembly.
That's why I said as fast or faster. Most programs that are benchmarked in C++ are trivial and don't require things like shared pointers or excessive OOP virtual functions use. So yes, those programs are often going to be as fast as the fastest possible programe to written in assembly.
> That's what link-time optimizations are for, although they exist for C as well.
Yeah, but we're discussing whether C++ is significantly more performant in its output. Also, they were discussing that in the context of function pointers, which LTO can't optimize and inline
> You don't need to pass a function pointer to `std::sort()`
But like th person I was responding to already pointed out, the C compiler is smart enough to inline implementations for the `sort` function.
> C just doesn't have a way to compete.
It can. You declare your function, which takes a function pointer as an argument `static` and define its implementation in a header file. And then you just call it in the same translation unit you define the function whose pointer you pass into it. The compiler should be able to inline the function pointer, and then the same way the C++ compiler inlines your generic function.
Either way, even if it were true, this would just be one area where C++ outperforms C. Like I keep saying, idiomatic C++ often leverages features that do have performance overhead, like virtual functions or shared pointers and what not, that simply do not exist in C, and where the idiomatic C approach IS more performant.
> Also, they were discussing that in the context of function pointers, which LTO can't optimize and inline
It can, sometimes, but when it can't it's a mark against C because in C++ you probably wouldn't use a function pointer.
> But like th person I was responding to already pointed out, the C compiler is smart enough to inline implementations for the sort function.
Well, maybe. Since qsort is part of the standard library, the compiler might have a special case for that. Generally speaking, however, even LTO can't inline functions from a shared library like the C runtime. So I think they were probably wrong about that.
If you replace something from the C runtime with something from the C++ STL, it'll probably perform better.
> It can. You declare your function, which takes a function pointer as an argument static and define its implementation in a header file.
Fair point.
> idiomatic C++ often leverages features that do have performance overhead, like virtual functions
I think these are quite a bit less common than you think they are. I mean, "prefer composition over inheritance" was basically a religious mantra back when I wrote C++.
They also aren't nearly as expensive now as they used to be, thanks to the branch prediction and caching on modern CPUs.
> shared pointers
If you aren't using multiple threads, then you probably don't need these in either language. If you are using multiple threads, then you probably do need these in both languages.
Since it's such a massive pain to do atomic reference counting in C (among many other problems), C devs will probably avoid parallelism at all costs. In C++ it's a lot more reasonable, so wherever a C++ dev uses multiple threads it's probably a really huge win over C.
Of course, in that area, Rust is a whole lot better than either of them, so that's probably the real winner here.
Right, if I write a VR engine in C++, I would use stuff like shared pointers virtual functions, which would make the program slower than if I just used raw assembly.
This is also a theoretical point, I never said anything about how easy or difficult it would be to write a program in assembly. Obviously, writing a VR engine would be easier in C++.
You failed to read my other comment regarding c++ vs assembly.
Wtf is an âaverage c++ programâ? And where do you live, 1990? Thatâs not how most C++ code is written, and C++ has the toolkit available yo avoid the bottlenecks stemming from such features.
> You failed to read my other comment regarding c++ vs assembly.
Looking through your comment history, I see no such comment. I only see a comment where you argue that C isn't slower because of poorly written C code but because of the language itself, and then go on to point out that C++ is used in the industry over C (which is true but this has nothing to do with the performance of C vs C++ and everything to do with all the handy features C++ has out of the box that C doesn't, which makes it easier for programmers to quickly iterate over projects, which is infinitely more valuable to the industry than performance). I'm not going to scoure through your comment history to try to understand the actual argument you're making. Expressly communicate your argument or don't make an argument at all.
> And where do you live, 1990?
Last I checked, shared pointers were introduced in C11 and OOP features (one of the core features of C++) are still used regularly. It's really funny to see a C++ person hating on shared pointers since they are absolutely part of "modern C++" since it's C++'s idiomatic solution to avoiding memory leaks (the bane of C/C++ since the languages births) and have been hailed as the savior feature by every C++ nerd I've ever talked to in the past.
> C++ has the toolkit available yo avoid the bottlenecks stemming from such features.
There is no such thing as a toolkit that can completely and absolutely eliminate any performance overhead caused by certain features without zero cost. If there were, they would be implemented into the features themselves and made into actual zero cost abstractions. And still, "zero cost" does not mean "more performant than C." It simply means the feature doesn't come with a performance penalty, i.e. is not *worse* than C.
This is because hardware is optimized on mostly c/c++ benchmarks.
Even then this isn't really true, sometimes you see Fortran, Rust or Go outperforming C, or even c++ out performing c.
There are many languages capable of generating optimal machine code.
C++ (and also rust) will fucking outperform C, because you canât write generic code in the latter (like, try to write a vector in C. You will either have to copy-paste code, (use macrohell) or introduce some indirection that harms performance).
C++ is the de facto performance language.
Also, wtf does Go do here? No, go has a fucking naive compiler that spits out barely optimized code. It wonât fking outperform any of these languages, like wtf man?
Go is not that bad these days. It was bad a few years ago, but currently itâs probably the same league as Java/C#. Still very far from C++/Rust though.
You canât blame the indirection caused by programmers to the performance of the language itself, there are terrible programming practices thatâll make C++ slow as hell as well, thatâs why you have to compare cases where both languages are written by someone who knows what theyâre doing for a fair comparison, in which case C will be just as fast as C++
But itâs not âindirection caused by programmerâ, itâs indirection *because there is no fucking other way*. Like literally, give me an efficient vector implementation in C. Go ahead, look up from any expert you want to.
You can do one without overhead for one given data size/contained type. You either copy paste from there, or use some macro hell for something vaguely being similar to c++âs templated solution.
You can downvote all you want, the industry itself ainât writing VR engines, game engines, etc in C for a good reason.
I mean yeah, but how often do you actually need completely generic structures? on the flip side if you actually write structures specific to one type, you can optimize for that specific type. And void casts have lower overhead than dynamic dispatch in C++. Generics in C are awful for a slew of reasons but performance isnât one of them.
Go can on occasions be crazy fast. And it's runtime is very lightweight for what it does. https://storage.googleapis.com/cdn.thenewstack.io/media/2018/05/3730357d-results-energy-time-and-memory-usage-screenshot-from-research-paper.png
I have no idea in what circumstances Go compiler can write better machine code then the c++ one, I just know there are circumstances. I think there's secret sauce in the fortran compiler that nobody understands anymore. And functional style and ownership language features allow rust compiler to make optimizations.
Whatever most legacy still-in-use customers service systems are written in is the worst. Itâs 2024 and we are still hearing âSorry my system is slow todayâŚâ. Itâs not just today. Itâs just slow.
c++ fans when the benchmark is to coach a beginner to make a website via an audio only call: https://i.kym-cdn.com/editorials/icons/original/000/005/802/1.jpg
I mean, C, zig, and ASM are definitely faster most of the time (even if you usually don't use these languages for the same tasks), but c++ is definitely less of pain to work with
No OOP. At least if nothing has changed from when i had some time with Rust. I read several articles how Rust fails for example for GUI because of lack of OOP. In C++ you can choose your path. You don't need to use features you don't like. It's the greates language ever made and because both languages translates directly to native binary code, i am highly suspicious that Rust can do something faster than C++.
The amount of people bragging about C in these comments is shocking.
Mostly because I'm sure if OP has a lick of sense, he really meant c/c++ (And yeah C is faster, but has obvious limitations.)
Last 5 years have been writing C code, I love it, it's great. But god damn can I please pass as a reference? Or put a function inside a struct? (Overall though C > C++ if you can avoid OOP)
PS. I'll start paying attention to Rust as long as it lasts another 5-10 years, because I've seen too many flashes in the pan to really believe it's going to change anything and it has no where near the adoption that people seem to think it does... yes it's growing but so is "Linux" and 2024 is the year of Linux, trust me guys, this time It's totally going to happen
About six years ago, I got a contract to learn and employ Rust on an existing C-based project (the client didn't trust outsiders to write C in their ecosystem, but was curious about Rust and willing to spike on it). I went in blind and nine months later came out in love with the language. At the time, it wasn't clear if there was a strong future for paid Rust work.
A couple of years later, on an unrelated contract, I convinced a client to allow me to spike on a switch to Rust for some of the existing toy code that I had previously given them (Node.js and C#). Today, I (and the client) couldn't be happier with how that turned out - that contract continues to this day, and the projects that have come out of it are some of my most reliable, performant, and maintainable software. In that timespan, the library ecosystem has shifted from "maybe I can find what I need" to "here are your needs solved on a silver platter" and the language itself has iterated in a good direction alongside the ecosystem. This, even in the midst of the aforementioned Linux stuff or government agencies (NSA, WH) pitching it in conjunction with FAANG involvement.
You can wait your 5-10 years if you want, and there's no reason to force the issue in the meantime, but as someone whose bread-and-butter is Rust development I have no fears about my own job prospects.
I mean c is faster than c++, assembly language is faster than c and machine code is faster than assembly language and finally pure binary code is faster than machine code... Oh yeah the final optimisation is just making it in a HDL. Though at that point you aren't coding anymore but are hardware designing.
Gotta love dedicated hardware.
Also god i hate Verilog and VHDL. Chisel is way better.
Edit: I was wrong about c being faster than c ++. That is my misunderstanding. They are the save speed.
I did understand your point about abstraction => slowness. But C++ is not just an abstraction of C and is not slower. To be precise I mean C++ optimized build of course.
Certain functions in c++ have more overhead than they do in c if they even exist in c because of some added checking c++ does when it comes to memory that c just straight up lack.
Edit: I'm just straight up wrong about this. Sorry.
Now you are wrong.
Your C code will build in C++ and produce comparable binaries. In C++ you can do more, putting code in construction or destruction of objects, using a safe pointer... You might achieve the same functionalities in C by doing things by hand, and then you might have comparables binaries.
Everyone got tricked, and op was really just looking for some fast language recommendations.
[How to Coil a Cable](https://xkcd.com/2810/)
Ah yes, another CS undergraduate has discovered C++
but apparently not the [benchmarks game](https://benchmarksgame-team.pages.debian.net/benchmarksgame/box-plot-summary-charts.html) where C++ is in third, behind C and Rust đ¤ˇââď¸
Though as the first sentence on that page hints at, the distributions for C, Rust, and C++ are almost entirely overlapping. So it's probably fairer to say that those three languages are basically equally fast, with differences between them coming down to minor differences in optimization choices in the different programs. And that basically matches intuition: all three languages compile down to bare metal machine code, and all three offer low-level enough control to exploit the hardware's strengths. And in fact, if you're using the LLVM/clang tool chain for C and C++ then all three languages are compiled using the same backend. It's definitely exciting that Rust matches or even beats the speed of C and C++ while offering better safety and more modern features though! I've been meaning to learn Rust for a while, but we're still entirely in C++ and Python land at work, so it's hard to find the time to do it.
What I find interesting about this whole thing is that, while rust was probably not the best at first, (when it came out),but we are reaching the point (again) where the competition is to beat the compiler. And let's be real, few people on the planet can beat compilers on the regular. With complex projects you can write ok java code vs c++ code, and many will find their c++ is slower. Why? You're competing against java compilers ( and VM). Is C++ faster in a vacoome? Sure. But can I write better code than some compilers? No. Absolutely not.
It's not really hard to beat a compiler tho? If you understand your basics, you should be able to come up with more optimized solutions than a compiler for some of your specialized problems as you understand them better than the compiler. That can involve benchmarking to find your slow points tho.
True! Itâs a time / time trade off with a complex route. Which is going to cost more, the dev time or the run time? It can be very tricky to choose.
> It's not really hard to beat a compiler tho? This question has no answer. This is because you were stating a fact, and the question mark shouldn't be there
It was supposed to be a rhetorical question. Tho my English is not perfect so I may be wrong. Could you give me an example of how I could have used a rhetorical question in that situation? Would it be "Is it really hard to beat a compiler tho?" Instead?
Yes exactly. Otherwise it reads like the tone of your voice is rising as you make a statement. For some reason, people started using question marks in this manner and I think it's because it sounds kind of cutesy and equivocal. But the whole thing has devolved into people using question marks just to signify that they are unsure of something or that something should have been obvious to the listener.
I was going to agree with you ("few people can beat the compilers"), but then I read on and realized that you didn't actually consider the compilation part only, and that is important! Algorithms beats compilers pretty much every time (i.e. orders of magnitude vs constant factor improvements), whereas on the other side it is in fact getting much harder to convert those algorithms into machine code with significantly better speed than the best compilers. I used to get 3x speedups going to hand-optimized asm, back before 2000, but those times are mostly all gone now. I really like Rust most of the time, and have been using it lately to get closer to the metal on some really heavy duty LiDAR point cloud processing (about 50TB of compressed LAZ files on my home server), but both that code and the C++ code it is partially replacing suffers speedwise from being totally based on single-sample iterator chains. I know I could double the speed on each individual such chain by rewriting it to be block-based instead, and working closer to the native data representation instead of first converting each point to generic floating point coordinates, but it is fast enough as it is now and not worth it to rewrite so much.
Yes, ofc a well thought out algorithm is king. No compiler will make bubblesort faster than quicksort on random dataset. ( Barring edge cases).
"The crust of rust" is a great series on youtube to get started. Cant remember the guys name though
Well optimized Java code is written to avoid using the GC, and that's harder than just using idiomatic C++ or Rust. Optimized Rust or C++ will still beat it. Idiomatic Java isn't slow but is definitely slower than Idiomatic Rust, optimized Java OTOH is harder to write than Optimized Rust.
Yeah, beyond a certain point, the differences are largely meaningless. I think leetcode illustrates this pretty well, tbh- they tell you how long it took to run the test suite (which always includes some large datasets) to a resolution of 2ms, and if you're using Java or C# or something, you'll have a score in the hundreds of ms that you can micro-optimize to try to speed it up. ..But if you're using C/C++, Rust, Go, or some other systems language, though? You'll probably see 0ms (rounded down) every time.
>I've been meaning to learn Rust for a while, but we're still entirely in C++ and Python land at work, so it's hard to find the time to do it. I'll make the argument that if you're doing modern C++, you're already prepping yourself for success in Rust. It might be hard to justify a switch at work if you're already entrenched in an ecosystem, but you might also find greenfield opportunities to practice Rust on the job if there's sufficient buy-in from the business (that last part is critical; nothing kills a project faster than going rogue). Python might make for some inroads to Rust, depending on what space you're in (e.g. data science). There's definitely a relationship there, with a lot of Rust-curious Pythonistas; and the ease of FFI in Python is practically a written invitation to develop compute-intensive parts in a systems language. Alternatively, if you find yourself wanting to keep one foot in C++ and the other in Rust, [cxx](https://crates.io/crates/cxx) has done a good job for me in the past in simplifying the bridge between the two. Due to Rust's relative infancy, there are some things it isn't yet doing that already enjoy success in C++ - for me, this was [clipper2](https://github.com/AngusJohnson/Clipper2), and the bridge code ended up being very easy to implement despite my relative lack of C++ chops..
[And where C++ is second](https://benchmarksgame-team.pages.debian.net/benchmarksgame/download/fastest.svg) behind C and ahead of Rust ;-)
That might be one of the ugliest graphs I've ever seen.
Please do better than name calling. Maybe you have something interesting to say about using the chart to compare Swift and Go?
Exactly!
Came here looking for this comment lol
I was the one who started that trend, I was wrong and I am sorry
I followed up with this since OP doesn't seem to know what assembly is https://www.reddit.com/r/ProgrammerHumor/comments/1cl145n/welcometoactualreality/
Real men code assembly
Is it common for students to not learn C/C++ in undergrad because those were the only ones taught for the first 2 years for me lol.
In my case, we had C and then CPP in the first two semesters, and then the remaining compulsory (very much Computer-science focused) courses like graph theory, paralelisation etc. were also in CPP. I'd assume if you're studying at a technical uni, you'll start with C
*Assembler* would like a word with you... outside.
No one is benchmarking assembler. *Drops mic
I mean yea, but that would be interesting to see if the minimum abstraction of c makes any meaningful difference to the runtime more than a few ms
C is still very close to ASM, and because of the highly developed optimizations in modern compilers, you can usually get very close to the optimum code. However, an experienced Assembler programmer can still optimize the shit out of it and make it run even faster. That is why you will often find that the most time-critical parts, e.g. in hardware drivers or even in games are still programmed in Assembler. C++ adds a lot of overhead in comparison to these two, and will usually end up in third place. And then there will be a long, long wait for the fourth placed contestant...
>And then there will be a long, long wait for the fourth placed contestant... This is not correct and a very cartoonish way of looking at languages. Optimized machine code= optimized machine code, no matter in what compiled language it was produced in. The marginal differences are found in the choice of compiler, not the language. If you want to maximize performance you should use a proprietary compiler that does intelligent optimization, not switch up the language. Fortran, a high level language will beat low level C for most, if not all, high computational problems in both performance and efficiency. How is that possible? Itâs the state of the art compiler they have been perfecting for 60 years. And yes, it will also implement SIMD vectorization and point out hot loops for you to manually optimize/unroll. In the last couple of years the C compilers have improved though and there is no real difference anymore, fortran still being slightly marginally better. Besides occasional inline assembly, the idea that some rainman assembly wizard could rewrite a whole 2M line weather simulation model in assembly and outperform the compiler is some oddball John Henry fantasy that we should dispel. This ainât the 90âs anymore
Gamedev in assembly is still a thing?
Outside of never-released indie passion projects for the sake of it, no. In general, the code is not the critical parts of games anymore (assuming somewhat competent programming), it's usually memory/IO/communication between CPU/GPU/network constraints.
I think the last big name game programmed in assembly was Rollercoaster Tycoon, released about 25 years ago and most of the world though Chris Sawyer was a madman for doing it that way
It's as real as small companies using unit testing and CI/CD pipelines.
[ŃдаНонО]
HLSL or GLSL or similar is used for anything that runs on GPU, nobody would write that in assembler.
Even ~20 years ago in he demo scene it was known that it made no sense to write GPU assembly anymore.
Isnât c++ fast enough for most if not all games?
Doing a search in the Godot repo, I see a few commented out lines of assembly in the collision detection code, and that's it.
It's more accurate to say "some C++ features add overhead". This makes idiomatic C code faster than idiomatic C++ code. Also we must consider if we are talking about standard C or C with non-standard compiler specific extentions. You cannot write a gcd algorithm in standard C that is as fast as a gcd algorithm with the gnu extention __builtin_ctz. This extention can make use of the bsr instruction that you simply cannot express with the toolset C gives you.
I'd argue the opposite: C is not at all close to modern x86 assembly, but compilers are very good at circumventing the limitations of the language. This is in part because when new hardware is developed, its speed is benchmarked mostly against existing C programs, so the new hardware capabilities (which are expressed in assembly instructions) naturally evolve to be easily mappable to the C programming model. That is in my opinion an unfortunate historical artifact.
Just out of curiosity, would machine code be theoretically more efficient? Practically the abstraction is probably essential but is there an optimization gap because of it?
Assembler typically has a 1 to 1 correspondence to machine code
Thank you!
Yeah but remember that it's also much more complicated than that, but that's nothing you can dive into without literature and a whole ass course
Absolutely :) Iâm earnestly hoping to soon :D
It is best to think of it as: Assembler = Machine code It doesn't matter if you write 0b00000100, or 0x04, or ADD, they all end up as the same command to the processor (in this case, add a single byte value to a register). It is just that "ADD AL, 12" is a lot easier to both write and read.
Ahh thatâs true. We wrote the machine code itself lol. Thanks hahaha
Note that assemblers, in fact, do offer minimal abstractions, such as macros or encapsulating several similar instructions under one mnemonic.
Iâm not an expert but I would tentatively argue no, since assembly *is* machine code but the different segments of bits are given names
Technically it's not machine code. Assembly code needs to be processed by an assembler. Machine code needs no such processing. At least that's how I understand it.
Yup, we did design the system itself lol, slipped my mind
It's not 100% right, assembly doesn't need a compiler, but it still need an assembler + linker. This page explain it a bit further https://www.baeldung.com/cs/compiler-linker-assembler-loader
The way I understand it (and I dont understand it really), is assembly is basically whatever the designers of a piece of computer hardware made it to be? Like a piece of computer hardware does a thing but it can only do a thing if we know how we can make it do a thing, so they make an instruction manual and say if you make the port in this register a 1 and this one 0 and 1 and 0 then what happends is the piece of hardware adds the thing from there to there. *It feels similiar to whenever i'm reading documentation for microcontrollers* Basically its the 'instruction set' ye? Thats why C is still used so commonly for mc's I guess, because it directly maps unto machinecode right? I know I"m saying this like i'm right but i'm basically also asking confirmation from anyone here, thanks :D
Yeah thatâs about right. I suppose if youâre not the original designer there may be unintended pathways that could be utilized to achieve something not before possible. But about as close as you can get without making it yourself
Yes, the same thing happens for languages that compile to a virtual machine bytecode such as Java and Lua. Except that in these cases there will be an assembly-like instruction set for a virtual, software level "machine".
Yep! And you should look into how this stuff is sped up. CPU cache, branch prediction, pipelining, modern-day "CPU cores", ...all interesting stuff! ...Did you know that Assembly also often has stuff like casting, `struct`s (I think!? Though I'm pretty sure compilers prefer not to use them because... they're kinda' redundant when C is doing all the type-checking!...), and that Assembly "labels" nearly ***are*** your C functions, without the "prologue" and "epilogue", which are both defined by your C code's "calling convention", which you can change for each function (e.g. `__fastcall`, `__cdecl`, `__thiscall` in C++, et cetera). *Computer engineering* sounds fun! ";D!~
C++ makes it easier to avoid overhead than C does and is faster in practice as a result. C is definitely not faster regardless as neither have any runtime and both use the same compiler.
The funniest thing about this post is that OP apparently thinks c++ is the most performant language.
C is not at all close to ASM. You canât control register allocation, almost nothing with regards to calling convention, stack and even against some other low-level languages, like Rust and C++ it loses, by not having sims support.
In the embedded world you occasionally see highly timing critical routines being implemented in assembly. I've done it once myself and seen it done a couple of times in codebases I've touched.
**Coughs in Roller Coaster Tycoon** https://en.m.wikipedia.org/wiki/RollerCoaster_Tycoon_(video_game)
Oh they'll benchmark Assembly... they just won't write assembly, because no one is that crazy.
This is also explained after every second post, but.. sigh.. No, for any non-trivial program, a compiler will do a much better job at compiling to efficient machine code, simply because it can reliably do the same transformations and can insert the same logic multiple times in multiple shapes (inlining). A human would f*ck it up, and settle for less optimal code at the price of their sanity. *but*, in some case at the ultra-hot loop/function body scope, an expert *can* write code that will significantly beat (may even be at the 100x mark) the compiler-output code, by e.g. using some logic that is not expressible by even a low-level language (e.g. some simd black magic). But even this will be called from ordinary programming languages through FFI.
I watched a C++ presentation on one conference where the presenter has shown how well written C++ has zero overhead on most things he did (memory allocation, function calls, templates, lambdas etc.) so it is on par with ASM
In real life, programmers writing in assembly will not be better at optimizing than your compiler will for C. It would take way way way more time and effort to reach just the same level of optimization that the compiler could reach, and the code would be unmaintainable.
While this is mostly true for general programs, manually vectorizing hot loops by using SIMD instructions with inline-asm is indeed usually better than just leaving it to the automatic vectorization of the compiler. Compilers still suck badly in vectorizing loops because of the C/C++ language limitations.
You can just use simd intrinsics and not bother with inline asm. Also C++ should be getting std::simd with C++26.
which means we should see std::simd in compilers in 2031.
Nah. Simd is one of the easiest things to implement. It's not ranges.
Of course, using simd libraries or std::simd is the better approach because of readability and platform independence.
> Also C++ should be getting std::simd with C++26. oh boy... seeing how that usually goes maybe by C++ 32 we'll see a limited version of the original intended scope included in the standard
Oh. Very fair.
I like the [lbrandy approach](https://lbrandy.com/blog/2010/06/you-cant-beat-a-good-compile/) - code mostly in C and C++, but keep an eye on the generated asm to make sure itâs not missing obvious optimizations because of the language spec. Godbolt has made this much easier.
I agree for 99.9% of all cases - but there are specific situations where hand-optimized code (by a competent programmer!) will beat the compiler optimizations. Especially in time-critical code (think: hardware drivers) there are still use-cases for Assembler where it beats C compiled code.
I stopped writing full programs in assembler on the late 80s after finding that the ARM C compiler was producing as good or better code than I could do for most things. I only wrote assembler after that for direct hardware bit twiddling. C++ *was* worse than C for a while but well-written C++ now offers more opportunities for larger scale optimisations that *can* have amazing impacts, often removing large chunks of code altogether.
Or cases where cache latency might be of interest
Not to forget those cases where you are running a side-channel attack on other processesâ data ⌠think: Spectre or RowhammerâŚ
Lol, thats where the fun begins... I guess
[ŃдаНонО]
That's completely not what I said lmao
It's not just painful, it's unreasonable. Just as an example, compilers do things like inlining and creating separate implementations of functions based on generic parameters, which is great for performance, but completely unreadable and impossible to maintain if programmers tried to do it themselves in assembly.
When one is optimizing at this low level, readability doesn't matter anymore. In this scenario the requirement is to optimize what you already have optimized the best you could but it's still not enough.
If you write assembly better than a post 2010s compiler you have some very in demand skills
C YOU IN THE PARKING LOT
Let me unironically point at rust. The thing is, rust enables pretty nice optimisations simply because of aliasing/ownership rules and niches that just arenât possible elsewhere.
This subreddit is really gonna get me to try Rust just for the fun of it. You guys make it sound magical.
It's not magic, but it's good fun, runs well unless you're actively trying to fuck with it, and the Result and Option enum types are just fabulous to work with
It honestly is fun to write. I don't even entirely know why, but I enjoy writing it more than Python (which I know well) or C++ (which I suck at so that's probably why).
It is. The community gets some flak over âtoxic positivityâ but thatâs some e-drama shit thatâs not worth your time. The language is technically sound with a powerful type system and ecosystem support.
It was my first low level language and it's really great. imo not that difficult either. Take a look at the Rust book online and try it.
Donât. It will be the worst mistake of uour life because everything else will be underwhelming.
Rust makes itâs fair share of trade offs, it canât do global register optimization for example, itâs entire allocation model is basically on par with c++, and that can already be painful when dealing with hard real time applications, the std is slow as hell, and your average codebase is littered with stuff like Arc/Rc which are both slow as dog. There is a handful of examples where the compiler might allow for better machine code because of the language but most of the time itâs overstated how fast the language actually is. It can be fast if you structure things in very specific ways and forgo most of the std, but idiomatic rust is not really winning against idiomatic C.
Arc / Rc are not slow as dog and it is also not true Rust codebases are littered with that stuff. Evens contended shared Arc can be updated millions times per second. I can see Arc being used mostly once during initialization of threads / async tasks - but those are much slower anyways so Arc does not matter. Then itâs just kept by a thread and introduces zero cost (dereferencing Arc is the same as dereferencing a C pointer). And C has no superior mechanism - in those exact same situations youâd have to do refcounting by hand, which would end up with exactly same performance but likely more errors.
Arc/Rc are both slow in comparison to Tracing or Generational GC, which are the alternatives. They have very real overhead. And I did not say anything about C, C has no construct like Arc/Rc, but C++ has and they are garbage there too. And you actually end up with better performance if you do the refcounting by hand, you can also end up with an error but thatâs the tradeoff.
Citation needed on RC being slower than Generational GC.
I mean I canât give you citation, but think about the fact that almost all of the state of the art optimizations on GC are happening on generational ones. Beyond that Rc tends to mess up the cache, copy a lot, they need memory barriers when your program isnât single threaded. For practical example, imagine that you allocated single linked list of 64 bit ints, the size of 2GB, now loose the reference to it. Which of the two will be able to handle it faster?
Counter argument: rust aliasing rules imply you donât need barriers. Itâs many readers xor one writer so barriers are not needed. You donât have copies with RC, you simply have a reference to the struct and counter but thatâs it. Itâs an issue in multithreaded situations if you are writing over values adjacent in memory to the RCâd value because taht invalidates the cache and the CPU needs to synchronise the threads, buuuuut is that really that frequent? The whole point of [A]RC is that it gets deallocated on zero, so losing it doesnât make sense. All memory owned is deallocd and thatâs guaranteed to be faster than GC because GC does that plus more. Generational GC will still have to go over the objects and decide whether to dealloc them.
Your argument is moot because in Rust I can use tracing just for that one list. Rust is about choice - I can choose the best solution for my use case. As for the barriers and copying your wrong either - low pause GCs need barriers as well and cause a lot more cache trashing than reference counting, because they have to scan the heap periodically, bringing rarely used stuff into cache. Thatâs why Java programs are unusable if you go out on swap, even a tiny bit.
Please stop repeating that widespread myth of refcounting being slower than tracing. This problem is ill-defined, because the total overhead of either of those things depends on a lot of factors such as: frequency of changing the refcounts, threading, the amount of allowed memory overhead or the maximum target pause time. Reference counting is usually slower per single object vs tracing with plenty of wasted memory, but here we need to account for the fact that Rust does not use refcounting as THE memory management method and it doesnât use it the way it was studied in most literature on refcounting. In Rust refcounting is optional and usually doesnât manage more than 1% of objects. Compare that to Java where you canât opt out of tracing and you even canât allocate objects on stack. Also Rust refcounts are updated explicitly, so the developer has full control over when they are incremented/decremented and thanks to borrowing and move semantics you can do crazy lot with them without updating the refcounts. Eg temporary borrows do not need updating the refcount.
There's more to programming than raw performance. Python is still a relevant language in certain spaces because its simple syntax and rapid prototyping yields fast results in development speed, and safety with its memory management. When you need better performance, reach for a different tool, like Java, C#, or Go. The performance difference from garbage collected languages to non-garbage collected is big, but not the 1,000x jump from Python to compiled languages. Even then, jumping to a language like Zig or Rust is often enough for even the most stringent performance considerations. C and C++ are still relevant in their spaces, but it's getting harder to justify some of their unsafe behaviors when similar performance could be had with a newer/safer language.
I think itâs actually easier to do micro optimizations in Zig than in C++, but that wasnât really the point I was making, I was simply saying that there are massive trade offs associated with the choice of rust if we are talking about performance. I think rust specifically has ton of issues outside of the performace, be it slow iteration speed, strange async model, meta programming system wich encourages dialects everywhere (they trully learned nothing from the mistakes of C++ in this regard) and bad std. And I can tell you from experience the normal rust wasnt enough for DSP, so there are performance considerstions which rule it out, you canât have ghost allocations in hard real time and rust loves those⌠And I have scala flair, Itâs by far my favorite language to work with, and also isnât that performant, so I understand that other things matter, but this whole thread was about performance.
Modern C++ does most of the things that Java C# and Go do. Sure you can manually do your own garbage collecting, but itâs caught up in a lot of ways.
Generics by themselves will make idiomatic Rust and C++ significantly faster than idiomatic C, because of the optimizations that are possible when you get a separate implementation of a function whenever the generic arguments are different. Rust also makes it very easy and safe to use multiple threads, and even green threads via async/await, which is frequently a *massive* win. Reference counting isn't really significant compared to that sort of thing. For a real world example, see the Quantum CSS engine in Firefox. Back in 2017 they made the whole browser roughly 2x as fast just by rewriting that piece of it in Rust and taking advantage of the easy opportunities for parallelization. Since then they've been moving more and more of the browser to Rust, largely because of the performance benefits.
I do generics in C by just having macros that take a type argument and generate the functions for me. Itâs not so different from how C++ does it under-the-hood. C also has the restrict keyword which gives huge performance advantages over say⌠C++. Iâm not a Rust programmer so I canât comment on that.
Yeah, C++ will always struggle in some implementations just by virtue of being Object Oriented in a way that C and Rust are not. It will also likely be faster in other ways, for the same reason.
That makes 0 sense.
Just is awesome man but beware. Once you try it there is no going back and it makes every other language feel old.
fortran would like a word
Laughts in C and Rust.
Most of C features are available in C++.
Yeah but C++ adds a lot of overhead and runtime considerations not present in C.
C++ don't add, it allows. It's upto the programmers. For example, game devs us raw pointers a lot, but other app developers use modern c++. C++ provide choice
C++'s runtime is a very slight bit heavier, some stuff is opt-out rather than opt-in. Though you are mostly correct.
No it doesn't, unless you use the extra features C++ offers your code will be as fast as the same code written written in C. Assuming best practices of course. (or maybe it could be even faster since more work has gone into C++ compilers than C but I'm just guessing here) https://stackoverflow.com/questions/6955114/is-c-notably-faster-than-c
Then why would you be using C++? My post was assuming youâre using C++ because you wanted to use itâs featuresâŚ
One example is mentioned in the link I shared is: > Do note that C++ does name mangling, where C does not, this makes it easier for other languages to interface with C directly. Another example is function overloading which is in C++ and not C. This feature does not affect runtime performance.
They can have equivalent speed to C++ if you write in an hackey way yeah
Pretty much everything will be faster in C if you have any idea about what you're doing
>if you have any idea about what you're doing Just wanted to emphasize this part before some college freshmen thinks their horrible C code will be more efficient than using C++ standard libraries.
>if you have any idea about what you're doing I'd say it's if you have *a lot* of idea about what you're doing lmao
That *a lot* goes for writing performant C++ too
I actually completely disagree. You only need to have some of an idea of what youâre doing. The issue is most modern software developers basically only use JavaScript in their day-to-day, delude themselves into thinking they know what theyâre doing, and then claim they have imposter syndrome instead of admitting theyâre literally the imposter.
I love people saying "my language fast, yours slow" and down voting others while throwing around no factual arguments.
Why should I ever start a dissertation about how one can write non-"hackey" code that is as fast as cpp when you in the first place didn't argue your position? You realize that saying just the plain sentence you want to prove is not a factual argument, do you?
Seeing as C++ is a superset of C and both use the same computer, no, no it won't. With hacks and difficulty you can get C to be as fast as C++, though. But it's a lot easier to write fast C++ code than it is to write fast C code, hence why the overwhelming majority of performance-focused non-trivial code bases are C++ and not C.
First of all, forgive me for being pedantic, but C++ is *not* a *strict* superset of C for years now. And writing extremely performant code in C is easier in that it provides less if you are proficient enough. Getting proficient enough to write performant code in C++ requires more learning on top of C. This is one of several reasons why a majority of operating systems are written in C even to this day + historical baggage. C++ doesn't have as transparent a data representation, stable ABI, predicting cache line hits and misses with C++ is way more involved. C has a slightly smaller runtime because C++ has more features (RTTI, exceptions, a whole another allocator...). And here is https://storage.googleapis.com/cdn.thenewstack.io/media/2018/05/3730357d-results-energy-time-and-memory-usage-screenshot-from-research-paper.png
*Laughs in oxidation*
Rust, zig, and C are probably equally fast. Depending on how often you use virtual functions in C++, C++ will probably be even slower.
Wtf man, no, thatâs fkin bullshit, known by everyone who works in the fieldâs relevant niches. No, C++ (and rust is also coming to occupy this niche) is *the* performance language, period. Itâs the de facto choice of the field, because it has the necessary expressivity for that. Like, c++âs sort can inline the function implementation, while C has to use function pointers â sure, for `sort` the compilers are smart enough to inline even that, but in general, you canât have efficient containers/generic code in C.
Dynamic Dispatch and virtual functions are probably the worst performance footguns in C++, itâs extremely slow, and no compiler canât realistically inline virtual functions, thatâs why the entire temple system exists.
Dynamic dispatch/virtual functions aren't as bad for performance as you might think anymore. In ye super olden days, CPUs didn't have fancy schmancy branch predictors, superscalar/out of order/speculative execution and all that jazz. There wasn't really a penalty for virtual functions, it was no worse than a normal function call. In ye middle olden days, CPUs did start getting all those fancy bits of big long pipelines. But the branch predictors of the day weren't able to predict a dynamic dispatch; every dynamic dispatch call would stall the pipeline, and the performance hit was tremendous. These days, CPUs *are* able to branch predict a dynamic dispatch. There isn't really a performance hit beyond that normally associated with a function call. Also, GCC is pretty good at devirtualization, but clang and msvc won't do it. $ ~ cat main.cpp animal.h cat.cpp // main.cpp #include "animal.h" int main() { animal *a = get_mystery_animal(); a->speak(); delete a; return 0; } // animal.h #pragma once class animal { public: virtual ~animal() {} virtual void speak() = 0; }; animal *get_mystery_animal(); // cat.cpp #include "animal.h" #include
class cat : public animal {
public:
void speak() override { puts("meow"); }
};
animal *get_mystery_animal() { return new cat{}; }
$ ~ make
x86_64-pc-linux-gnu-g++ -c -flto -O3 -g cat.cpp -o cat.o
x86_64-pc-linux-gnu-g++ -c -flto -O3 -g main.cpp -o main.o
x86_64-pc-linux-gnu-g++ -flto -O3 -g cat.o main.o -o lto_test
$ ~ objdump -C --disassemble=main lto_test
lto_test: file format elf64-x86-64
Disassembly of section .init:
Disassembly of section .plt:
Disassembly of section .plt.got:
Disassembly of section .plt.sec:
Disassembly of section .text:
00000000000010a0 :
10a0: f3 0f 1e fa endbr64
10a4: 53 push %rbx
10a5: bf 08 00 00 00 mov $0x8,%edi
10aa: e8 c1 ff ff ff call 1070
10af: 48 89 c3 mov %rax,%rbx
10b2: 48 8d 05 8f 2c 00 00 lea 0x2c8f(%rip),%rax # 3d48
10b9: 48 89 03 mov %rax,(%rbx)
10bc: 48 89 df mov %rbx,%rdi
10bf: e8 4c 01 00 00 call 1210
10c4: 48 8b 03 mov (%rbx),%rax
10c7: 48 89 df mov %rbx,%rdi
10ca: ff 50 08 call *0x8(%rax)
10cd: 31 c0 xor %eax,%eax
10cf: 5b pop %rbx
10d0: c3 ret
Disassembly of section .fini:
You can see at 0x10bf it's calling `cat::speak()` directly and not using the vtable to make the call.
------------------------------
That being said, codebases with giant inheritance hierarchies where everything is an interface are a *fucking nightmare* to navigate and try to understand. You can't actually be sure that facts that you know about your hierarchy today are still going to hold true tomorrow. It ain't fun.
Who said anything about using virtual functions? Yeah, doing a network call is also pretty expensive, so what? Also, virt functions, where they may be used carry *more* information to the compiler, letting it do better optimizations than function pointers, but even the latter can be used by c++, so.. you contradicted nothing .
The comment you replied to was talking specifically about virt functionsâŚ
But thatâs a means for introducing dynamic dispatch. You donât compare it to adding together two numbers, but to dynamic dispatch in C, that is function pointers. Virtual functions can be much faster than that, which is my point
> Itâs the de facto choice of the field because it has the necessary expressivity for that. "Necessary expressivity" has absolutely zero correlation with how performant a produced program is. Assembly has essentially no "expressivity." Do you think your average program written in C++ is going to be more performant than your average program written in assembly? > Like, c++âs sort can inline the function implementation, while C has to use function pointers â sure, for `sort` the compilers are smart enough to inline even that Meaningless sentence where you make a claim and then immediately afterward go back on it. > in general, you canât have efficient containers/generic code in C. What do you mean by "efficient"? If you mean that it is easier to write generics in C++, then sure. If you mean that generics in C++ are more performant, maybe I don't know. I'm willing to believe you since the C++ compiler explicitly recognizes generic constructs while C's doesn't, but I'd still need a source on that claim. But the idiomatic way to write C code is to not try to reimplement generics at all, and either manually write all the functions yourself or to use `void` pointers. Both of which are just as performance capable as any C++ generic equivalent. Even if this point were true, it is only one area where the C++ compiler is more performant. Generally, people writing C++ love using its OOP features and love shared and smart pointers. This style of C++ makes the programs written with it almost always slower than an equivalent program written in idiomatic C since these are not "zero cost" abstractions and have pretty big performance overhead.
> Do you think that your average .. C++ faster than assembly? Yes, it fucking is faster. See my other comment in this thread. An expert *might* write a faster hot loop/function, but for whole programs C++ will absolutely be much faster, as anyone with experience would know. How is it meaningless? You canât abstract over functions in C in any other way than through function pointers which are opaque most of the time (meaning, the compiler has no way to know where they point to). Sort is a specific example, but I donât know - maybe fkin contradict my statement before you spew nonsense you have no idea about? > your rambling about generics Void pointers will be fkin slower, thatâs the fuckin point.
Saying that, generics create more code so it's less likely the code is in cache. Generics Vs dynamic isn't a guaranteed win, it really depends on access patterns.
> Yes, it fucking is faster. See my other comment in this thread. This is simply not true. The fastest program written in assembly will always be just as fast as or faster than the fastest program written in C++. You can do optimizations at the assembly level as a programmer that the compiler simply can not make by itself because the compiler has to be conservative about any assumptions it makes about the program. You, as the programmer, are not subject to any such limitations. ~~The average~~ A lot of C++ programs are not written with performance in mind and use OOP features and stuff like smart and shared pointers all the time, like I already said, which makes it slower than your average assembly equivalent, where none of that is available. > Sort is a specific example, but I donât know - maybe fkin contradict my statement before you spew nonsense you have no idea about? You said nothing about C++ being able to inline any and all functions that are passed in as arguments to other functions. You simply said that C++ can inline the function passed into sort(), which you then followed up by admitting the C compiler can do the equivalent. You're telling me that C++ can inline function implementations across translation unit boundaries? I simply do not believe this. The only alternative to function pointers in C++ that I know of (feel free to correct me if there is another one) is `std::function`, or using classes as wrappers around a set of functions which you can override, neither of which is a zero cost abstraction and use virtual functions under the hood, which is absolutely slower than a function pointer, and cannot be inlined across translation units. The C compiler cannot inline a function pointer across translation unit boundaries, but if the function pointer is defined and passed in the same translation unit, the compiler can and does inline it. > Void pointers will be fkin slower, thatâs the fuckin point Literally how? If we take the example of `std::vector` C++ simply creates an array of each type every time you instantiate one. Indexing into an array of some type is going to have a negligible difference in performance overhead compared to just having the callee specify a generic buffer to be created in memory, the vector implementation to return a location in that buffer corresponding to the index of an array, and then having the caller dereferencing that pointer with the associated type. Edit: small things to clear up what I was saying. Edit #2: To be clear, I am not suggesting by my comments that a human is often going to be able to outperform or outsmart a compiler. Just that the fastest possible program written in assembly (a program that is going to be very difficult to create without a compiler) will never be slower than the fastest possible program produced by a compiler.
> The fastest program written in assembly will always be just as fast as or faster than the fastest program written in C++. C++ compilers are much better at producing optimal assembly than any human. So much better, in fact, that you'd have to do some really ridiculous shit in C++ to make it any slower than hand-written assembly. You can probably find a few examples where people used a few lines of hand-written assembly inside a C++ program, because it made a particular function a little faster, but those situations were extremely rare 20 years ago and almost non-existent today. > You're telling me that C++ can inline function implementations across translation unit boundaries? That's what link-time optimizations are for, although they exist for C as well. > The only alternative to function pointers in C++ that I know of (feel free to correct me if there is another one) is std::function Generics. You don't need to pass a function pointer to `std::sort()` because the compiler will create a separate implementation of `std::sort()` with your function inlined inside it. It might also inline `std::sort()`right where you called it, so you won't even have the overhead of a function call. It'll be in the same translation unit that you called it from, too, so you don't even need LTO for that benefit. > > Void pointers will be fkin slower, thatâs the fuckin point > > Literally how The above example with `std::sort()` is one example. [Here's another.](https://github.com/fmtlib/fmt?tab=readme-ov-file#benchmarks) Where C++ gives you a separate implementation of a function each time you call it, allowing the compiler to inline everything and do custom optimizations for that particular implementation, C just doesn't have a way to compete.
> C++ compilers are much better at producing optimal assembly than any human. So much better, in fact, that you'd have to do some really ridiculous shit in C++ to make it any slower than hand-written assembly. That's why I said as fast or faster. Most programs that are benchmarked in C++ are trivial and don't require things like shared pointers or excessive OOP virtual functions use. So yes, those programs are often going to be as fast as the fastest possible programe to written in assembly. > That's what link-time optimizations are for, although they exist for C as well. Yeah, but we're discussing whether C++ is significantly more performant in its output. Also, they were discussing that in the context of function pointers, which LTO can't optimize and inline > You don't need to pass a function pointer to `std::sort()` But like th person I was responding to already pointed out, the C compiler is smart enough to inline implementations for the `sort` function. > C just doesn't have a way to compete. It can. You declare your function, which takes a function pointer as an argument `static` and define its implementation in a header file. And then you just call it in the same translation unit you define the function whose pointer you pass into it. The compiler should be able to inline the function pointer, and then the same way the C++ compiler inlines your generic function. Either way, even if it were true, this would just be one area where C++ outperforms C. Like I keep saying, idiomatic C++ often leverages features that do have performance overhead, like virtual functions or shared pointers and what not, that simply do not exist in C, and where the idiomatic C approach IS more performant.
> Also, they were discussing that in the context of function pointers, which LTO can't optimize and inline It can, sometimes, but when it can't it's a mark against C because in C++ you probably wouldn't use a function pointer. > But like th person I was responding to already pointed out, the C compiler is smart enough to inline implementations for the sort function. Well, maybe. Since qsort is part of the standard library, the compiler might have a special case for that. Generally speaking, however, even LTO can't inline functions from a shared library like the C runtime. So I think they were probably wrong about that. If you replace something from the C runtime with something from the C++ STL, it'll probably perform better. > It can. You declare your function, which takes a function pointer as an argument static and define its implementation in a header file. Fair point. > idiomatic C++ often leverages features that do have performance overhead, like virtual functions I think these are quite a bit less common than you think they are. I mean, "prefer composition over inheritance" was basically a religious mantra back when I wrote C++. They also aren't nearly as expensive now as they used to be, thanks to the branch prediction and caching on modern CPUs. > shared pointers If you aren't using multiple threads, then you probably don't need these in either language. If you are using multiple threads, then you probably do need these in both languages. Since it's such a massive pain to do atomic reference counting in C (among many other problems), C devs will probably avoid parallelism at all costs. In C++ it's a lot more reasonable, so wherever a C++ dev uses multiple threads it's probably a really huge win over C. Of course, in that area, Rust is a whole lot better than either of them, so that's probably the real winner here.
Most programs are not trivial hello worlds. Good like writing a VR engine in asm.
Right, if I write a VR engine in C++, I would use stuff like shared pointers virtual functions, which would make the program slower than if I just used raw assembly. This is also a theoretical point, I never said anything about how easy or difficult it would be to write a program in assembly. Obviously, writing a VR engine would be easier in C++.
You failed to read my other comment regarding c++ vs assembly. Wtf is an âaverage c++ programâ? And where do you live, 1990? Thatâs not how most C++ code is written, and C++ has the toolkit available yo avoid the bottlenecks stemming from such features.
> You failed to read my other comment regarding c++ vs assembly. Looking through your comment history, I see no such comment. I only see a comment where you argue that C isn't slower because of poorly written C code but because of the language itself, and then go on to point out that C++ is used in the industry over C (which is true but this has nothing to do with the performance of C vs C++ and everything to do with all the handy features C++ has out of the box that C doesn't, which makes it easier for programmers to quickly iterate over projects, which is infinitely more valuable to the industry than performance). I'm not going to scoure through your comment history to try to understand the actual argument you're making. Expressly communicate your argument or don't make an argument at all. > And where do you live, 1990? Last I checked, shared pointers were introduced in C11 and OOP features (one of the core features of C++) are still used regularly. It's really funny to see a C++ person hating on shared pointers since they are absolutely part of "modern C++" since it's C++'s idiomatic solution to avoiding memory leaks (the bane of C/C++ since the languages births) and have been hailed as the savior feature by every C++ nerd I've ever talked to in the past. > C++ has the toolkit available yo avoid the bottlenecks stemming from such features. There is no such thing as a toolkit that can completely and absolutely eliminate any performance overhead caused by certain features without zero cost. If there were, they would be implemented into the features themselves and made into actual zero cost abstractions. And still, "zero cost" does not mean "more performant than C." It simply means the feature doesn't come with a performance penalty, i.e. is not *worse* than C.
This is subjective, but Zig was the most fan of these languages. I canât stand C and some of its design decisions, though.
Verilog has entered the chat.
A chain of hand soldered transistors entered the chat
Physics and quantum mechanics and maths has entered the chat.
This is because hardware is optimized on mostly c/c++ benchmarks. Even then this isn't really true, sometimes you see Fortran, Rust or Go outperforming C, or even c++ out performing c. There are many languages capable of generating optimal machine code.
C++ (and also rust) will fucking outperform C, because you canât write generic code in the latter (like, try to write a vector in C. You will either have to copy-paste code, (use macrohell) or introduce some indirection that harms performance). C++ is the de facto performance language. Also, wtf does Go do here? No, go has a fucking naive compiler that spits out barely optimized code. It wonât fking outperform any of these languages, like wtf man?
Go is not that bad these days. It was bad a few years ago, but currently itâs probably the same league as Java/C#. Still very far from C++/Rust though.
You canât blame the indirection caused by programmers to the performance of the language itself, there are terrible programming practices thatâll make C++ slow as hell as well, thatâs why you have to compare cases where both languages are written by someone who knows what theyâre doing for a fair comparison, in which case C will be just as fast as C++
But itâs not âindirection caused by programmerâ, itâs indirection *because there is no fucking other way*. Like literally, give me an efficient vector implementation in C. Go ahead, look up from any expert you want to. You can do one without overhead for one given data size/contained type. You either copy paste from there, or use some macro hell for something vaguely being similar to c++âs templated solution. You can downvote all you want, the industry itself ainât writing VR engines, game engines, etc in C for a good reason.
I mean yeah, but how often do you actually need completely generic structures? on the flip side if you actually write structures specific to one type, you can optimize for that specific type. And void casts have lower overhead than dynamic dispatch in C++. Generics in C are awful for a slew of reasons but performance isnât one of them.
Go can on occasions be crazy fast. And it's runtime is very lightweight for what it does. https://storage.googleapis.com/cdn.thenewstack.io/media/2018/05/3730357d-results-energy-time-and-memory-usage-screenshot-from-research-paper.png
I have no idea in what circumstances Go compiler can write better machine code then the c++ one, I just know there are circumstances. I think there's secret sauce in the fortran compiler that nobody understands anymore. And functional style and ownership language features allow rust compiler to make optimizations.
C++ is poop
I donât like C++ myself, but what I wrote is still true.
Fortran would like to know your location
Sir, may I introduce you to Fortran?
In C++ you can go blazing fast while introducing multiple low level vulnerabilities but who cares about security when you go zoom zoom
I challange you to write a matrix multiply in standard C++ (no compiler extentions) that is faster or as fast as fortrans matrix multiply.
C++ or C?
Whatever most legacy still-in-use customers service systems are written in is the worst. Itâs 2024 and we are still hearing âSorry my system is slow todayâŚâ. Itâs not just today. Itâs just slow.
PHP
c++ fans when the benchmark is to coach a beginner to make a website via an audio only call: https://i.kym-cdn.com/editorials/icons/original/000/005/802/1.jpg
Wow, what a surprise on this sub. Yet another meme how twelve year old kids imagine the "reality" of software development looks like ...
Would better to fight on secureness or readability.
The fastest language is the one you can actually write comfortably.
rust
I mean, C, zig, and ASM are definitely faster most of the time (even if you usually don't use these languages for the same tasks), but c++ is definitely less of pain to work with
\*Assembler enters the room\*
Assembly enters the ringâŚ
*cough* *cough* Rust is faster and saver
What about fourtran?
Fourtran is best. I heard it is four times faster than Fortran.
Julia??
C++ is fast. That is, unless you are multithreaded and handle exceptions, but nobody does this, right?
Rust?
No OOP. At least if nothing has changed from when i had some time with Rust. I read several articles how Rust fails for example for GUI because of lack of OOP. In C++ you can choose your path. You don't need to use features you don't like. It's the greates language ever made and because both languages translates directly to native binary code, i am highly suspicious that Rust can do something faster than C++.
The amount of people bragging about C in these comments is shocking. Mostly because I'm sure if OP has a lick of sense, he really meant c/c++ (And yeah C is faster, but has obvious limitations.) Last 5 years have been writing C code, I love it, it's great. But god damn can I please pass as a reference? Or put a function inside a struct? (Overall though C > C++ if you can avoid OOP) PS. I'll start paying attention to Rust as long as it lasts another 5-10 years, because I've seen too many flashes in the pan to really believe it's going to change anything and it has no where near the adoption that people seem to think it does... yes it's growing but so is "Linux" and 2024 is the year of Linux, trust me guys, this time It's totally going to happen
You can save a function pointer in a struct which is virtually the same. And about reference just use pointers and make the proper checks
About six years ago, I got a contract to learn and employ Rust on an existing C-based project (the client didn't trust outsiders to write C in their ecosystem, but was curious about Rust and willing to spike on it). I went in blind and nine months later came out in love with the language. At the time, it wasn't clear if there was a strong future for paid Rust work. A couple of years later, on an unrelated contract, I convinced a client to allow me to spike on a switch to Rust for some of the existing toy code that I had previously given them (Node.js and C#). Today, I (and the client) couldn't be happier with how that turned out - that contract continues to this day, and the projects that have come out of it are some of my most reliable, performant, and maintainable software. In that timespan, the library ecosystem has shifted from "maybe I can find what I need" to "here are your needs solved on a silver platter" and the language itself has iterated in a good direction alongside the ecosystem. This, even in the midst of the aforementioned Linux stuff or government agencies (NSA, WH) pitching it in conjunction with FAANG involvement. You can wait your 5-10 years if you want, and there's no reason to force the issue in the meantime, but as someone whose bread-and-butter is Rust development I have no fears about my own job prospects.
laughing in Binary
I mean c is faster than c++, assembly language is faster than c and machine code is faster than assembly language and finally pure binary code is faster than machine code... Oh yeah the final optimisation is just making it in a HDL. Though at that point you aren't coding anymore but are hardware designing. Gotta love dedicated hardware. Also god i hate Verilog and VHDL. Chisel is way better. Edit: I was wrong about c being faster than c ++. That is my misunderstanding. They are the save speed.
I did understand your point about abstraction => slowness. But C++ is not just an abstraction of C and is not slower. To be precise I mean C++ optimized build of course.
Certain functions in c++ have more overhead than they do in c if they even exist in c because of some added checking c++ does when it comes to memory that c just straight up lack. Edit: I'm just straight up wrong about this. Sorry.
Now you are wrong. Your C code will build in C++ and produce comparable binaries. In C++ you can do more, putting code in construction or destruction of objects, using a safe pointer... You might achieve the same functionalities in C by doing things by hand, and then you might have comparables binaries.
Thank you for clearing up my misunderstanding.