Live data from Hacker News

C++'s `noexcept` can sometimes help or hurt performance

16bpp.net

101–110 of 166 posts

Re: C++'s `noexcept` can sometimes help or hurt performance

#101

Earlier quoted context omitted.

-fno-exceptions only prevents you from calling throw. If you don't want overhead likely you want -fno-asynchronous-unwind-tables + that clang flag that specifies that extern "C" functions don't throw

Looking how the docs for https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#ind... How does that affect code generation? It reads as only effecting debug information and binary size to my untrained eyes.

And based on a few clang discourse threads, it only removes .eh_frame

I think this only effects binary size, which I understand smaller binaries can load faster but not being able to get stacktraces for debuggers and profilers seems like a loss

Re: C++'s `noexcept` can sometimes help or hurt performance

#102

Oh man, don't get me started. This was a point in a talk I gave years ago called "Please Please Help the Compiler" (what I thought was a clever cut at the conventional wisdom at the time of "Don't Try to Help the Compiler") I work on MSVC backend. I argued pretty strenuously at the time that noexcept was costly and being marketed incorrectly. Perhaps the costs are worth it, but none the less there is a cost The reaso…

Doesn't every function already need exception unwinding metadata? If the function is marked noexcept, then can't you write the logical equivalent of "Unwinding instructions: Don't." and the exception dispatcher can call std::terminate when it sees that?

Re: C++'s `noexcept` can sometimes help or hurt performance

#103

Oh man, don't get me started. This was a point in a talk I gave years ago called "Please Please Help the Compiler" (what I thought was a clever cut at the conventional wisdom at the time of "Don't Try to Help the Compiler") I work on MSVC backend. I argued pretty strenuously at the time that noexcept was costly and being marketed incorrectly. Perhaps the costs are worth it, but none the less there is a cost The reaso…

> there is a guarantee here that noexcept functions don't throw. std::terminate has to be called. That has to be implemented Could you elaborate on how this causes more overhead than without noexcept? The fact that something has to be done when throwing an exception is true in both cases, right?. Naively it'd seem like without noexcept, you raise the exception; and with noexcept, you call std::terminate instead. Pres…

If you're on one of the platforms with sane exception handling, it's a matter of emitting different assembly code for the landing pad so that when unwinding it calls std::terminate instead of running destructors for the local scope. Zero additional overhead. If you're on old 32-bit Microsoft Windows using MSVC 6 or something, well, you might have problems. One of the lesser ones being increased overhead for noexcept.

Re: C++'s `noexcept` can sometimes help or hurt performance

#104

Oh man, don't get me started. This was a point in a talk I gave years ago called "Please Please Help the Compiler" (what I thought was a clever cut at the conventional wisdom at the time of "Don't Try to Help the Compiler") I work on MSVC backend. I argued pretty strenuously at the time that noexcept was costly and being marketed incorrectly. Perhaps the costs are worth it, but none the less there is a cost The reaso…

I’m curious: where does the overhead of try/catch come from in a “zero-overhead” implementation? Is it just that it forces the stack to be “sufficiently unwindable” in a way that might make it hard to apply optimisations that significantly alter the structure of the CFG? I could see inlining and TCO being tricky perhaps? Or does Windows use a different implementation? Not sure if it uses the Itanium ABI or something…

Everyone keeps scanning over the inlining issues, which I think are much larger

“Zero overhead” refers to the actual functions code gen; there are still tables and stuff that have to be updated

Our implementation of noexcept for the single function case I think is fine now. There is a single extra bit in the exception function info which is checked by the unwinder. Other than requiring exception info in cases where we otherwise wouldn’t

The inlining case has always been both more complicated and more of a problem. If your language feature inhibits inlining in any situation you have a real problem

Re: C++'s `noexcept` can sometimes help or hurt performance

#105

Oh man, don't get me started. This was a point in a talk I gave years ago called "Please Please Help the Compiler" (what I thought was a clever cut at the conventional wisdom at the time of "Don't Try to Help the Compiler") I work on MSVC backend. I argued pretty strenuously at the time that noexcept was costly and being marketed incorrectly. Perhaps the costs are worth it, but none the less there is a cost The reaso…

It's kinda funny that C++ even in recent editions generally reaches for the UB gun to enable optimizations, but somehow noexcept ended up to mean "well actually, try/catch std::terminate". I bet most C++-damaged people would expect throwing in a noexcept function to simply be UB and potentially blow their heap off or something instead of being neatly defined behavior with invisible overhead.

Re: C++'s `noexcept` can sometimes help or hurt performance

#106

Oh man, don't get me started. This was a point in a talk I gave years ago called "Please Please Help the Compiler" (what I thought was a clever cut at the conventional wisdom at the time of "Don't Try to Help the Compiler") I work on MSVC backend. I argued pretty strenuously at the time that noexcept was costly and being marketed incorrectly. Perhaps the costs are worth it, but none the less there is a cost The reaso…

> I argued then that if instead noexcept violations were undefined, we could ignore all this, and instead just treat it as the pure optimization it was being marketed as (ie, help prove a region can't throw, so we can elide entire try/catch blocks etc). Do you know if the reasoning for originally switching noexcept violations from UB to calling std::terminate was documented anywhere? The corresponding meeting minutes…

I think WG21 has been violently against adding additional UB to the language, because of some hacker news articles a decade ago about people being alarmed at null pointer checks being elided or things happening that didn’t match their expectation in signed int overflow or whatever. Generally it seems a view of spread that compiler implementers view undefined behavior as a license to party, that we’re generally having too much fun, and are not to be trusted.

In reality undefined behavior is useful in the sense that (like this case) it allows us to not have to write code to consider and handle certain situations - code which may make all situations slower, or allows certain optimizations to exist which work 99% of the time.

Regarding “not pan out”: I think the overhead of noexcept for the single function call case is fine, and inlining is and has always been the issue.

Re: C++'s `noexcept` can sometimes help or hurt performance

#107
post #79

Earlier quoted context omitted.

Dude I am going to blow your mind

Eeeermm... I haven't heard an explosion, but 4+ hours has passed. Are you alive there, dude? Jokes aside - I'm always happy to be corrected, so please go on if I made a mistake somewhere.

Determining if a function throws is a pretty basic bit of information collected in bottom up codegen (or during pre pass of a whole program optimization) and in no sense NP hard. Compilers have been doing it for decades and it’s useful

Noexcept on the surface is useful, except for the terminate guarantee, which requires a ton of work to avoid metadata size growth and hurts inlining. If violations of noexcept were UB and it was a pure optimization hint the world would be much better

Re: C++'s `noexcept` can sometimes help or hurt performance

#108

Is there any compiler option to have it yell at you if you mark something that can throw as `noexcept`, which seems to be the cause of (at least some of) the slowdowns where the compiler is forced to accommodate with `std::terminate`? I feel like these situations are more commonly mistakes , and not the user wanting to "collapse" exceptions into terminations. So the current approach to dealing with these cases seems…

No, calling throw in a noexcept function is a defined behavior (call std::terminate), and that behavior is not a diagnostic

I think maybe WG21 was concerned a compiler engineer would be clever if throwing in noexcept were UB, for example and assume any block that throws is unreachable and could just be removed along with all blocks it postdominates. Compiler guys love optimizations that just remove code. The fastest and smallest code is code that can’t run and doesn’t exist

Re: C++'s `noexcept` can sometimes help or hurt performance

#109
post #37
post #2

> I didn't know std::uniform_int_distribution doesn't actually produce the same results on different compilers I think this is genuinely my biggest complaint about the C++ standard library. There are countless scenarios where you want deterministic random numbers (for testing if nothing else), so std's distributions are unusable. Fortunately you can just plug in Boost's implementation.

It's actually really important that uniform_int_distribution is implementation defined. The 'right' way to do it on one architecture is probably not the right way to do it on a different architecture. For instance, Apple's new CPUs has very fast division. A convenient and useful tool to implement uniform_int_distribution relies on using modulo. So the implementation that runs on Apple's new CPUs ought to use the modu…

Nobody is using standard library for high-performant random number implementations.

Re: C++'s `noexcept` can sometimes help or hurt performance

#110
This is super unrelated to the optimisation, and is just related to the cmake setup - instead of common.hpp having #ifdef USE_NOEXCEPT #define NOEXCEPT noexcept #else #define NOEXCEPT #endif

and cmake being:

    if (WITH_NOEXCEPT)
      message(STATUS "Using `noexcept` annotations (faster?)")
      target_compile_definitions(PSRayTracing_StaticLibrary PUBLIC USE_NOEXCEPT)
    else()
      message(STATUS "Turned off use of `noexcept` (slower?)")
    endif()
, the cmake could just be:

    if (WITH_NOEXCEPT)
      message(STATUS "Using `noexcept` annotations (faster?)")
      target_compile_definitions(PSRayTracing_StaticLibrary PUBLIC USE_NOEXCEPT=noexcept)
    else()
      message(STATUS "Turned off use of `noexcept` (slower?)")      target_compile_definitions(PSRayTracing_StaticLibrary PUBLIC USE_NOEXCEPT=)
    endif()
No need for these shared "common" config headers.

Back on topic, this doesn't surprise me. There's this idea that C++ is fast, and that people who work with C++ are focused on optimisation and in my experience there's as many of these theoretical ideas about performance which aren't backed up by numbers, but are now ingrained in people. See https://news.ycombinator.com/item?id=41095814 from last week for another example of dogmatic guidelines having the wrong impact.

Post reply on HN