Rendered at 19:15:28 GMT+0000 (Coordinated Universal Time) with Cloudflare Workers.
ralferoo 8 hours ago [-]
"I can recompile the entire thing from scratch in ~4.3s. That’s around ~900 TUs, including external dependencies, tests, and examples"
In 30 years of using C++ this is the first time I've ever come across "translation unit" being abbreviated to TU and it took a bit of effort to figure out what the author was trying to say. Not sure why they felt the need to abbreviate this when they explain PCH for instance, which is a far more commonly used term.
Thought I'd add the context here to help anyone else out.
pjmlp 8 hours ago [-]
It is quite common when being around WG21 stuff, just as info.
dataflow 4 hours ago [-]
> Not sure why they felt the need to abbreviate this
It's super common terminology for people around those spaces; they probably didn't even think about whether they should abbreviate it.
SuperV1234 1 hours ago [-]
I've updated the article to say "translation unit" the first time "TU" is introduced. The data was also incorrect due to an oversight on my part, and it's now much more accurate and ~50% faster across the board.
HexDecOctBin 46 minutes ago [-]
> Language features like templates are not the issue – the Standard Library is.
What sins does STL commits that make it slow if templates themselves are not slow, and what kind of template code doesn't bloat compile times? In my experience, C++ libraries are usually one order of magnitude or more slower to compile than equivalent C ones, and I always chalked it upto the language.
SuperV1234 1 hours ago [-]
Update & Apology:
I've fully updated the article with new benchmarks.
A reader pointed out that the GCC 16 Docker container I originally used was built with internal compiler assertions enabled, skewing the data and unfairly penalizing GCC.
I've re-measured everything on a proper release build (Fedora 44), and the compile times are ~50% faster across the board.
The article now reflects the accurate numbers, and I've added an appendix showing the exact cost of the debug assertions.
I sincerely apologize for the oversight.
leni536 9 hours ago [-]
libstdc++'s <print> is very heavy, reflection or not. AFAIK there is no inherent reason for it to be that heavy, fmtlib compiles faster.
<meta> is another question, it depends on string_view, vector, and possibly other parts. Maybe it's possible to make it leaner with more selective internal deps.
SuperV1234 1 hours ago [-]
The data was incorrect due to an oversight on my part (the Docker image I had used compiled GCC with internal assertions enabled).
Including <print> is still very heavy, but not as bad as before (from ~840ms to ~508ms)
craftit 9 hours ago [-]
I don't know the exact details, but I have heard (on C++ Weekly, I believe) that it offers some advantages when linking code compiled with different compiler versions. That said, I normally avoid it and use fmtlib to avoid the extra compile time. So it isn't clear if it is a win to me. Header-only libraries are great on small projects, but on large codebases with 1000's of files, it really hits you.
surajrmal 6 hours ago [-]
It also bloats binary size if you statically link libc++ because of localization, regardless if you care for it. This wasn't true for fmtlib because it doesn't support localization. stringstream has this same problem, but it's one of many reasons embedded has stuck with printf.
wjakob 8 hours ago [-]
I am very worried by feature creep in libc++ and libstdc++ and the harm that this inflicts on the wider C++ ecosystem. Transitive inclusion of large parts of the STL, and entangling of STL with core language features are both extremely bad. This should IMO be topic #1 of the committee but is barely even noticed. The mantra "It's okay, modules will save us" is naive and will not work.
CoastalCoder 8 hours ago [-]
I'm pretty late to this discussion, but...
I was somewhat horrified to discover that the STL ended up with a special role in the language spec. (IIRC, one of the tie-ins is initializer lists.)
IMHO it's far wiser to leave the standard library as something that isn't needed by the core language, and where users can (at least in principle) provide their own alternative implementation without needing compiler hacks.
I.e., those details are inherent in the definition of "library" in the C/C++ world.
jcranmer 4 hours ago [-]
Which languages have a standard library that contains nothing requiring intimate integration with the language implementation itself? I'm not aware of any, even limited-standard-library C included.
dataflow 4 hours ago [-]
> I was somewhat horrified to discover that the STL ended up with a special role in the language spec. (IIRC, one of the tie-ins is initializer lists.)
std::type_info? std::is_trivially_...?
direwolf20 7 hours ago [-]
Parts of the language being in the std namespace isn't really a problem. An implementation is free to treat initializer lists as a built-in type.
panzi 6 hours ago [-]
Is there an implementation that does that?
dataflow 4 hours ago [-]
With std::nullptr_t on MSVC, it's always there without any includes.
shadowgovt 5 hours ago [-]
The language specification is already larger than several classical tomes of fiction. A reader could choose to tuck in with the C++ spec, or with War and Peace.
And given how much of the language's spec is "The behavior is undefined when combining these two features," it's not really a tome that is safely ignored.
At this point, I cannot recommend C++ on any new project that some external factor such as safety certification (which "solves" the problem by adding yet more pages of stuff a developer must not do that the language syntactically supports and compiles but generates garbage output) isn't forcing my hand on.
As of 2026 C has eclipsed C++ in popularity on the TIOBE index; anecdotally, roboticists I've chatted with have told me they prefer to write core functionality as C modules and then weld them together into high-level behavior with a terser scripting DSL over trying to write the whole thing in C++ and hoping there's no undefined behavior hidden in the cracks that multiple layers of linters, sanitizers, and auto-certifiers have missed.
r2vcap 8 hours ago [-]
Yuck. I’ve already noticed compilation times increasing from C++17 to C++20, and this feature makes it much worse. I guess I’ll need to audit any reflection usage in third-party dependencies.
SuperV1234 1 hours ago [-]
Please check the article again -- I made a mistake in the original measurements (the Docker image I used had GCC compiled in debug mode) and now the (correct) times are ~50% faster across the board.
Not free, still need to audit, but much better than before. Sorry.
SuperV1234 4 days ago [-]
I ran some more measurements using import std; with a properly built module that includes reflection.
So PCH actually wins for just <meta>, and modules are not that much better than PCH for the larger example. Very disappointing.
SuperV1234 1 hours ago [-]
Update: I had originally used a Docker image with a version of GCC built with assertions enabled, skewing the results. I am sorry for that.
Modules are actually not that bad with a proper version of GCC. The checking assertions absolutely crippled C++23 module performance in the original run:
Modules (Basic 1 type): from 352.8 ms to 279.5 ms (-73.3 ms)
Modules (AoS Original): from 1,077.0 ms to 605.7 ms (-471.3 ms, ~43% faster)
There is plenty of zero cost abstractions in C++ (and Rust to some extend).
This talk just point that unique_ptr is not one of them due to the side effect of C++ move semantics being non destructive.
People that do not understand that should honestly stop to use it as an argument in favor of "there is no zero cost abstractions".
dataflow 4 hours ago [-]
This is a pretty flippant response to a rather insightful point by someone who isn't exactly a newbie to the language. They understand very well the implications of move being nondestructive and the point they're making stands nevertheless.
adev_ 4 hours ago [-]
Let me clarify something here (And my apologies if this looked a bit aggressive).
There is always a cost to abstraction, and that can take different form. In C++, it is often build time (and/or complexity). And Chandler, in his talk, is perfectly right about that.
But that does not change the validity of the C++ concept 'zero cost abstraction at *runtime*'. It is possible to get proper language abstractions while not sacrificing runtime performances.
I did get sharp on his comment because this talk is constantly posted by a specific C crowd that profoundly hate any form of abstraction and use it as a totem to justify terrible development practices.
If your language support zero cost abstraction and genericity, by the sake of god, use it... most of the time the impact in term compilation time is worth the benefits.
unique_ptr is a beautiful example of that btw.
dataflow 3 hours ago [-]
You're not only undeservedly dismissing very salient high-level points but also just completely missing the low-level ones. Even ignoring build times and looking only at execution times (and btw it's not just time that matters here), even function calls are not always zero-cost. For multiple reasons, some of which differ across compilers more than others.
Nobody is concluding you shouldn't write functions either.
adev_ 3 hours ago [-]
Then we disagree.
> (and btw it's not just time that matters here)
My remark is still valid. Even considering memory space and cognitive complexity.
> even function calls are not always zero-cost. For multiple reasons, some of which differ across compilers more than others
Divergence about the support of inlining in compiler implementation have nothing to do with the debate here. Some idiosyncrasy about C++ argument passing and lifetime might causes a cost in some specific scenario, still that is specific to C++.
It still does invalid the concept of zero runtime cost for abstraction.
As much as people like to dismiss it, Stepanov was right all along.
> Nobody is concluding you shouldn't write functions either.
Then, you will be surprised to learn that some 'devs' actually recommend exactly this and write guideline that minimize the number of function written. They tend to be from the same crowd that the one was describing before.
dalvrosa 8 hours ago [-]
Nice to learn about hyperfine
Compilation speed is a huge part of productivity and enjoying writing C++
jstimpfle 9 hours ago [-]
The hidden compile-time cost of <insert almost any C++ feature>
SuperV1234 8 hours ago [-]
Nah, many great features are extremely cheap. E.g. constexpr, templates, fold expressions, equality operator defaulting, concepts...
JamesTRexx 7 hours ago [-]
Until you try to add / modify a feature of the software and run into confusing template or operator or other C++ specific errors and need to deconstruct a larger part of the code to find (if possible) out where it comes from and spend even more time trying to correct it.
C++ is the opposite of simplicity and clarity in code.
kreco 8 hours ago [-]
Yes, but they are still all hidden.
direwolf20 7 hours ago [-]
constexpr means running code at compile time. template means duplicating lots of code lots of times. these are not cheap.
jeffbee 6 hours ago [-]
Yeah this is the very first time I am hearing that templates are "extremely cheap". Template instantiation is pretty much where my project spends all of its compilation time.
SuperV1234 1 hours ago [-]
It depends on what you are instantiating and how often you're doing so. Most people write templates in header files and instantiate them repeatedly in many many TUs.
In many cases it's possible to only declare the template in the header, explicitly instantiate it with a bunch of types in a single TU, and just find those definitions via linker.
jeffbee 53 minutes ago [-]
On the few times that I have looked at clang traces to try to speed up the build (which has never succeeded) the template instantiation mess largely arose from Abseil or libc++, which I can't do much about.
zombot 7 hours ago [-]
How is it hidden if you can measure it?
comandillos 5 hours ago [-]
just another piece to this jenga tower called c++.
if you want reflection maybe just use a language that was designed with reflection support since the beginning.
In 30 years of using C++ this is the first time I've ever come across "translation unit" being abbreviated to TU and it took a bit of effort to figure out what the author was trying to say. Not sure why they felt the need to abbreviate this when they explain PCH for instance, which is a far more commonly used term.
Thought I'd add the context here to help anyone else out.
It's super common terminology for people around those spaces; they probably didn't even think about whether they should abbreviate it.
What sins does STL commits that make it slow if templates themselves are not slow, and what kind of template code doesn't bloat compile times? In my experience, C++ libraries are usually one order of magnitude or more slower to compile than equivalent C ones, and I always chalked it upto the language.
I've fully updated the article with new benchmarks.
A reader pointed out that the GCC 16 Docker container I originally used was built with internal compiler assertions enabled, skewing the data and unfairly penalizing GCC.
I've re-measured everything on a proper release build (Fedora 44), and the compile times are ~50% faster across the board.
The article now reflects the accurate numbers, and I've added an appendix showing the exact cost of the debug assertions.
I sincerely apologize for the oversight.
<meta> is another question, it depends on string_view, vector, and possibly other parts. Maybe it's possible to make it leaner with more selective internal deps.
Including <print> is still very heavy, but not as bad as before (from ~840ms to ~508ms)
I was somewhat horrified to discover that the STL ended up with a special role in the language spec. (IIRC, one of the tie-ins is initializer lists.)
IMHO it's far wiser to leave the standard library as something that isn't needed by the core language, and where users can (at least in principle) provide their own alternative implementation without needing compiler hacks.
I.e., those details are inherent in the definition of "library" in the C/C++ world.
std::type_info? std::is_trivially_...?
And given how much of the language's spec is "The behavior is undefined when combining these two features," it's not really a tome that is safely ignored.
At this point, I cannot recommend C++ on any new project that some external factor such as safety certification (which "solves" the problem by adding yet more pages of stuff a developer must not do that the language syntactically supports and compiles but generates garbage output) isn't forcing my hand on.
As of 2026 C has eclipsed C++ in popularity on the TIOBE index; anecdotally, roboticists I've chatted with have told me they prefer to write core functionality as C modules and then weld them together into high-level behavior with a terser scripting DSL over trying to write the whole thing in C++ and hoping there's no undefined behavior hidden in the cracks that multiple layers of linters, sanitizers, and auto-certifiers have missed.
Not free, still need to audit, but much better than before. Sorry.
I first created the module via:
And then benchmarked with: The only "include" was import std;, nothing else.These are the results:
- Basic struct reflection: 352.8 ms
- Barry's AoS -> SoA example: 1.077 s
Compare that with PCH:
- Basic struct reflection: 208.7 ms
- Barry's AoS -> SoA example: 1.261 s
So PCH actually wins for just <meta>, and modules are not that much better than PCH for the larger example. Very disappointing.
Modules are actually not that bad with a proper version of GCC. The checking assertions absolutely crippled C++23 module performance in the original run:
Modules (Basic 1 type): from 352.8 ms to 279.5 ms (-73.3 ms) Modules (AoS Original): from 1,077.0 ms to 605.7 ms (-471.3 ms, ~43% faster)
Please check the update article for the new data.
This talk just point that unique_ptr is not one of them due to the side effect of C++ move semantics being non destructive.
People that do not understand that should honestly stop to use it as an argument in favor of "there is no zero cost abstractions".
There is always a cost to abstraction, and that can take different form. In C++, it is often build time (and/or complexity). And Chandler, in his talk, is perfectly right about that.
But that does not change the validity of the C++ concept 'zero cost abstraction at *runtime*'. It is possible to get proper language abstractions while not sacrificing runtime performances.
I did get sharp on his comment because this talk is constantly posted by a specific C crowd that profoundly hate any form of abstraction and use it as a totem to justify terrible development practices.
If your language support zero cost abstraction and genericity, by the sake of god, use it... most of the time the impact in term compilation time is worth the benefits.
unique_ptr is a beautiful example of that btw.
Nobody is concluding you shouldn't write functions either.
> (and btw it's not just time that matters here)
My remark is still valid. Even considering memory space and cognitive complexity.
> even function calls are not always zero-cost. For multiple reasons, some of which differ across compilers more than others
Divergence about the support of inlining in compiler implementation have nothing to do with the debate here. Some idiosyncrasy about C++ argument passing and lifetime might causes a cost in some specific scenario, still that is specific to C++.
It still does invalid the concept of zero runtime cost for abstraction.
As much as people like to dismiss it, Stepanov was right all along.
> Nobody is concluding you shouldn't write functions either.
Then, you will be surprised to learn that some 'devs' actually recommend exactly this and write guideline that minimize the number of function written. They tend to be from the same crowd that the one was describing before.
Compilation speed is a huge part of productivity and enjoying writing C++
C++ is the opposite of simplicity and clarity in code.
In many cases it's possible to only declare the template in the header, explicitly instantiate it with a bunch of types in a single TU, and just find those definitions via linker.