I don't want a discussion about when to and not to throw exceptions. I wish to resolve a simple issue. 99% of the time the argument for not throwing exceptions revolves around them being slow while the other side claims (with benchmark test) that the speed is not the issue. I've read numerous blogs, articles, and posts pertaining one side or the other. So which is it?
相关问题
- Sorting 3 numbers without branching [closed]
- Graphics.DrawImage() - Throws out of memory except
- Generic Generics in Managed C++
- Why am I getting UnauthorizedAccessException on th
- 求获取指定qq 资料的方法
One quick note here on the performance associated with catching exceptions.
When the execution path enters a 'try' block, nothing magical happens. There is no 'try' instruction, and no cost associated with either entering or exiting the try block. Information about the try block is stored in the method's metadata, and this metadata is used at runtime whenever an exception is raised. The execution engine walks down the stack looking for the first call that was contained in a try block. Any overhead associated with exception handling occurs only when exceptions are thrown.
If you compare them to return codes they are slow as hell. However as previous posters stated you don't want to throw in normal program operation so you only get the perf hit when a problem occurs and in the vast majority of cases performance no longer matters (as the exception implies a road-block anyway).
They're definately worth using over error codes, the advantages are vast IMO.
I'm on the "not slow" side - or more precisely "not slow enough to make it worth avoiding them in normal use". I've written two short articles about this. There are criticisms of the benchmark aspect, which are mostly down to "in real life there'd be more stack to go through, so you'd blow the cache etc" - but using error codes to work your way up the stack would also blow the cache, so I don't see that as a particularly good argument.
Just to make it clear - I don't support using exceptions where they're not logical. For instance,
int.TryParse
is entirely appropriate for converting data from a user. It's appropriate when reading a machine-generated file, where failure means "The file isn't in the format it's meant to be, I really don't want to try to handle this as I don't know what else might be wrong."When using exceptions in "only reasonable circumstances" I've never seen an application whose performance was significantly impaired by exceptions. Basically, exceptions shouldn't happen often unless you've got significant correctness issues, and if you've got significant correctness issues then performance isn't the biggest problem you face.
In release mode the overhead is minimal.
Unless you are going to be using exceptions for flow-control (example, non-local exits) in a recursive fashion, I doubt you will be able to notice the difference.
I have no idea what people are talking about when they say they are slow only if they are thrown.
EDIT: If Exceptions aren't thrown, then that means you are doing new Exception() or something like that. Otherwise the exception is going to cause the thread to be suspended, and the stack to be walked. This may be Ok in smaller situations, but in high-traffic websites, relying on exceptions as a workflow or execution path mechanism will certainly cause you performance problems. Exceptions, per se, aren't bad, and are useful for expressing exceptional conditions
The exception workflow in a .NET app uses first and second chance exceptions. For all exceptions, even if you are catching and handling them, the exception object is still created and the framework still has to walk the stack to look for a handler. If you catch and rethrow of course that is going to take longer - you are going to get a first-chance exception, catch it, rethrow it, causing another first-chance exception, which then doesn't find a handler, which then causes a second-chance exception.
Exceptions are also objects on the heap - so if you are throwing tons of exceptions, then you are causing both performance and memory issues.
Furthermore, according to my copy of "Performance Testing Microsoft .NET Web Applications" written by the ACE team:
"Exception handling is expensive. Execution of the involved thread is suspended while CLR recurses through the call stack in search of the right exception handler, and when it is found, the exception handler and some number of finally blocks must all have their chance to execute before regular processing can be performed."
My own experience in the field showed that reducing exceptions significantly helped performance. Of course, there are other things you take into account when performance testing - for example, if your Disk I/O is shot, or your queries are in the seconds, then that should be your focus. But finding and removing exceptions should be a vital part of that strategy.
On the Windows CLR, for a depth-8 call chain, throwing an exception is 750-times slower than checking and propagating a return value. (see below for benchmarks)
This high cost for exceptions is because the windows CLR integrates with something called Windows Structured Exception Handling. This enables exceptions to be properly caught and thrown across different runtimes and languages. However, it's very very slow.
Exceptions in the Mono runtime (on any platform) are much faster, because it does not integrate with SEH. However, there is functionality loss when passing exceptions across multiple runtimes because it doesn't use anything like SEH.
Here are abbreviated results from my benchmark of exceptions vs return values for the Windows CLR.
And here is the code..