Performance benchmarks can be tricky, especially when used to evaluate a feature of a programming language. In this case, by adding "no_inline" to both the version and pre-initializing the exception object, the difference in performance on my machine decreased to 2.8 times from 22 times. The question is, which benchmark version provides a better assessment of the feature.
The discussion about exception performance mainly focuses on the runtime performance implications of the exception process, which should be negligible. However, due to the current semantics of exception handling, the throw/catch process significantly affects control and data flow, leading most compilers to be more pessimistic about optimization.
The debate between error codes and exceptions seems like a false choice to me. Both have their strengths and weaknesses and should be used interchangeably in the same codebase depending on the circumstances.
In my opinion, the main advantage of exceptions is when there is a large distance between the point of error generation and the point in the program where there is the best information to handle the error. In such cases, monadic error handling would require every intermediary computation to handle the error, whereas exception propagation allows unrelated computations to essentially ignore the error state.
I would even suggest that C++ needs something like "Conditions and Restarts" as a more general exception mechanism.
> In this case, by adding "no_inline" to both the version and pre-initializing the exception object, the difference in performance on my machine decreased to 2.8 times from 22 times.
That’s not a realistic benchmark though. I’ve never seen real-world non-benchmark code which pre-initializes exceptions. They’re always created completely from scratch. Beyond it being uncommon, pre-initializing would also unnecessarily waste memory when you don’t throw the exception.
When it comes to no_inline, I think one should go the opposite direction. Because no_inline here just showed that error codes can be made slower when compiler knows less about code, bringing it closer to exceptions. What’s disputed though is not that you can make ordinary code slower, but that compilers will realistically make your exception-throwing code faster. So I’d annotate with always_inline instead.
Yeah, that why i mentioned that benchmarking features is always contentious and it's easy to devolve into semantic argument... but here we go.
I guess it depends on what you mean by realistic and what is the benchmark trying to do. If by realistic, we mean "representative" in a sense that this code captures a good approximation o real work code, then i would argue that the original benchmark is completely wrong.
My version focus on being precise : measuring one thing (exception handling) in isolation as much as possible.
With that perspective :
1 - The cost of error handling also depends on the amount of information being reported. In the orginal benchmark, on one side the author is sending basically one bit of information and the other a full string. Pre-allocating the error was a way to normalize for that.
2 - I looked at the code, and most of performance delta between the two version came from the error code being vectorize, no_inline was a way to normalize for that as well.
The discussion about exception performance mainly focuses on the runtime performance implications of the exception process, which should be negligible. However, due to the current semantics of exception handling, the throw/catch process significantly affects control and data flow, leading most compilers to be more pessimistic about optimization.
The debate between error codes and exceptions seems like a false choice to me. Both have their strengths and weaknesses and should be used interchangeably in the same codebase depending on the circumstances.
In my opinion, the main advantage of exceptions is when there is a large distance between the point of error generation and the point in the program where there is the best information to handle the error. In such cases, monadic error handling would require every intermediary computation to handle the error, whereas exception propagation allows unrelated computations to essentially ignore the error state.
I would even suggest that C++ needs something like "Conditions and Restarts" as a more general exception mechanism.