Live data from Hacker News

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

16bpp.net

1–10 of 166 posts

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

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

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

#3
Even a speedup of around 1% (if it is consistent and in a carefully controlled experiment) is significant for many workloads, if the workload is big enough.

The OP has this as in the fuzz, which it may be for that particular workload. But across a giant distributed system like youtube or Google search, it is a real gain.

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

#6
post #4

Shouldn't the compiler deduce noexcept for you?

The compiler can tell about the immediate function, but not any functions it calls.

If a function marked noexcept calls a function that throws an exception, then the program is terminated with an uncaught exception. A called function can throw through a non-noexcept function to a higher-level exception handler no problem.

So in order to avoid changing the semantics of the function, the compiler would have to be able to determine that that transitive closure of called functions dynamically don't throw, and that problem is undecidable, even assuming the requirement that "the compiler can see the source of all those functions" is somehow met, which it won't be.

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

#7
post #4

Shouldn't the compiler deduce noexcept for you?

No, noexcept confusingly doesn't mean "does not throw exceptions" in that sense. There is no constraint that says you can only call noexcept code from noexcept code - quite the opposite. Noexcept puts NO constraints on the code.

All noexcept does is catch any exception and immediately std::terminate. Confusingly this means that noexcept should really be called deathexcept, since any exception thrown within kills the program.

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

#8
I don't feel like this article illuminates anything about how noexcept works. The asm diff at the end suggests _there is no difference_ in the emitted code. I plugged it into godbolt myself and see absolutely no difference. https://godbolt.org/z/jdro5jdnG

It seems the selected example function may not be exercising noexcept. I suppose the assumption is that operator[] is something that can throw, but ... perhaps the machinery lives outside the function (so should really examine function calls), or is never emitted without a try/catch, or operator[] (though not marked noexcept...) doesn't throw b/c OOB is undefined behavior, or ... ?

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

#9
post #7
post #4

Shouldn't the compiler deduce noexcept for you?

No, noexcept confusingly doesn't mean "does not throw exceptions" in that sense. There is no constraint that says you can only call noexcept code from noexcept code - quite the opposite. Noexcept puts NO constraints on the code. All noexcept does is catch any exception and immediately std::terminate. Confusingly this means that noexcept should really be called deathexcept, since any exception thrown within kills the…

Oh, so it's like Rust's panic=abort

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

#10
That's quite interesting and a huge work has been done here, respect for that.

Here's what has jumped out at me: `noexcept` qualifier is not free in some cases, particularly, when a qualified function could actually throw, but is marked `noexcept`. In that case, a compiler still must set something up to fulfil the main `noexcept` promise - call `std::terminate()` if an exception is thrown. That means, that putting `noexcept` on each and every function blindly without any regard to whether the function could really throw or not (for example, `std::vector::push_back()` could throw on reallocation failure, hence if a `noexcept` qualified function call it, a compiler must take into account) doesn't actually test/benchmark/prove anything, since as the author correctly said, - you won't ever do this in a real production project. It would be really interesting to take a look into a full code of cases that showed very bad performance, however, here we're approaching the second issue: if that's the core benchmark code: https://github.com/define-private-public/PSRayTracing/blob/a... then unfortunately it's totally invalid since it measures time with the `std::chrono::system_clock` which isn't monotonic. Given how long the code required to run, it's almost certain that the clock has been adjusted several times...

Post reply on HN