You won't get a sense of how bad exceptions can be by using Godbolt. A lot of the magic of exceptions is handled behind the scenes by the compiler and/or the Itanium ABI. For example one disasterous consequence of using exceptions in GCC is that there is a global application wide lock used to manage stack unwinding.
This means that only one single thread can unwind a stack at a time and the lock is held from the start of the exception being thrown until the very last destructor is called. If you have a multicore server with 100 threads, and one of those threads throws an exception, you better hope that no other thread throws an exception because even if those two threads are entirely independent of one another, one of them will block.
> For example one disasterous consequence of using exceptions in GCC is that there is a global application wide lock used to manage stack unwinding.
This might have been (partially?) fixed? GCC Bug 71744 "Concurrently throwing exceptions is not scalable" is marked "RESOLVED FIXED" [0], and commit 6e80a1d164d1 in particular looks interesting:
> eliminate mutex in fast path of __register_frame
>
> <snip>
>
> This commit eliminates both the mutex and the sorted list from the atomic fast path, and replaces it with a btree that uses optimistic lock coupling during lookup. This allows for fully parallel unwinding and is essential to scale exception handling to large core counts.
I'm not particularly familiar with the unwinding machinery though so I don't know if the issue is fully resolved.
No one ever claimed that throwing exceptions is fast and quite honestly you should not care about the performance of that too much and instead make sure that exceptions are supposed to be exceptional.
What is interesting though is the impact of exceptions when they are not being thrown. This includes setup code (mostly avoided by good exception handling implementations) but also inhbited optimization opportunities and executable size bloat.
This means that only one single thread can unwind a stack at a time and the lock is held from the start of the exception being thrown until the very last destructor is called. If you have a multicore server with 100 threads, and one of those threads throws an exception, you better hope that no other thread throws an exception because even if those two threads are entirely independent of one another, one of them will block.
You won't see this by looking at Godbolt.