And yet, across the gulf of space, minds immeasurably superior to ours regarded this Earth [...] - War of the Worlds
A while ago, I wrote an article about the performance of exceptions, and in particular how they're not as expensive in release mode as people often assume from their experiences when debugging. A colleague then made me aware that in September 2006, Rico Mariani (MS performance guru) blogged about the page, in particular asking his readers to find the flaws in my analysis before he posted his own thoughts. Now, many of Rico's readers are a lot smarter than me and know a lot more about performance than I do (with Rico's knowledge of performance dwarfing mine to an embarrassing degree) so it's no surprise that their comments were by and large on target. It hasn't changed my view on exceptions, however it has made me think that perhaps I didn't lay the context of my article out clearly enough, focusing on the microbenchmark (which is of course flawed as any microbenchmark is).
The context of my article was effectively trying to provide a shot of reality into the frequent debate about when to use return values to indicate "error conditions" (whatever they may be in the particular situation - and that's the tricky bit) and when to use exceptions. Performance is usually cited as a reason to use return values; comments like "exceptions are very expensive" are very common. The aim of my original article was to show that those comments were generally repeated without any real idea of how expensive (or otherwise) exceptions are. So, rather than the "absolute" cost of exceptions being important to me, it's really the cost of throwing an exception relative to the cost of achieving the same end result via return codes. That accounts for some of the "hidden costs" mentioned by Rico's readers, such as cache misses due to popping up the stack several layers: if the stack needs to be popped in the exception case, achieving the same effect with return codes would still require the same level of "poppage". That being said, I willingly admit that the results give more of a "flavour" of the cost of exceptions than an accurate and exact figure.
There are various ways I could improve the benchmark, but it would still have been artificial, and could never have satisfied all the problems described in the blog entry. Instead of giving more and more figures showing performance at various stack levels, etc, I'll make a general statement:
If you ever get to the point where exceptions are significantly hurting your performance, you have problems in terms of your use of exceptions beyond just the performance.
In other words, in cases where performance is an important criterion for deciding not to use exceptions, there are other criteria which would also suggest avoiding exceptions for those cases - and those criteria are probably more important than the performance.
Sometimes there are things you can do about excessive exceptions - check whether an operation is valid
before trying it if you're the caller, provide a way of testing validity before the call (or using the
TryXXX pattern as per
TryParse) if you're the callee. Sometimes the API you're
using doesn't provide the appropriate calls, and that's where you could end up with exception-based
performance problems you genuinely can't avoid.
I don't intend to write a long article about when exceptions are and aren't appropriate - but there's a blog entry from Krzysztof Cwalina which neatly describes pretty much what I would write.
Back to the main page.