views:

3919

answers:

10

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?

Some links from the answers: Skeet, Mariani, Brumme.

A: 

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.

leppie
+82  A: 

I'm on the "not slow" side. 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.

Jon Skeet
Excellent article.
MusiGenesis
unfortunately, people are told exceptions are free, use them for trivial 'correct' functionality, they should be used as you say, when things have gone wrong - in 'exceptional' circumstances
gbjbaanb
Yes, people should certainly be aware that there's a performance cost associated with using exceptions inappropriately. I just think it's a non-issue when they *are* used appropriately :)
Jon Skeet
... 'appropriately'. amen to that.
gbjbaanb
Last sentence is gospel.
Jonathan C Dickinson
Another point worth of note: tryparse should be used when you can recover from a failure, otherwise parse will be faster than "if(!tryparse) throw"
Sklivvz
+2  A: 

The argument as I understand it is not that throwing exceptions are bad they are slow per se. Instead, it is about using the throw/catch construct as a first class way of controlling normal application logic, instead of more traditional conditional constructs.

Often in normal application logic you perform looping where the same action is repeated thousands/millions of times. In this case, with some very simple profiling (see the Stopwatch class), you can see for yourself that throwing an exception instead of say a simple if statement can turn out to be substantially slower.

In fact I once read that the .NET team at Microsoft introduced the TryXXXXX methods in .NET 2.0 to many of the base FCL types specifically because customers were complaining that performance of their applications was so slow.

It turns out in many cases this was because customers were attempting type conversion of values in a loop, and each attempt failed. An conversion exception was thrown and then caught by an exception handler that then swallowed the exception and continued the loop.

Microsoft now recommend the TryXXX methods should be used particularly in this situation to avoid such possible performance issues.

I could be wrong, but it sounds like you are not certain about the veracity of the "benchmarks" you have read about. Simple solution: Try it out for yourself.

Ash
I thought that internatlly those "try" functions use exceptions as well?
greg
These "Try" functions do not throw exceptions internally for a failure to Parse the input value. However they still throw exceptions for other error situations, such as ArgumentException.
Ash
+13  A: 

As MusiGenesis said, "Exceptions are slow in .NET if they are thrown"

So, yes, you don't want to throw too many of them. On my computer, a simple throw inside a loop, it took 9.5 seconds to throw 1000 exceptions, but that time would increase, were the exception to be buried inside a large stack.

That is why flow control should NOT be done by exceptions (I know your question didn't ask for anything other than the speed, but you can work that out yourself with a timed test). Sure, you should throw exceptions whenever something goes wrong. However, you should keep the number of things going wrong to a minimum. E.g. don't pass bad data to a function.

Ha, and every answer so far (including this) is talking about when to, and when not to throw exceptions. Ironic.


In fact, I entirely agree with Jon, and I hadn't seen his answer when I wrote this.

Vincent McNabb
"On my computer, a simple throw inside a loop, it took 9.5 seconds to throw 1000 exceptions." My guess is that that was running inside a debugger. In release mode, not under a debugger, I'd expect you to be able to throw several thousand per second. Slower with a large stack, but not *that* slow.
Jon Skeet
Jon: not my experience, It cost almost exactly the same in Release mode.
RBarryYoung
It's not release mode per se which makes the difference, it's running from within Visual studio. Use Ctrl-F5 rather than F5 to run without Visual studio's debugger attached; that debugger first inspects each and every exception (even those that are caught) and hence makes exceptions abnormally slow. - of course, that is in and of itself a real issue making your code harder to debug.
Eamon Nerbonne
A: 

I have never had any performance problem with exceptions. I use exceptions a lot -- I never use return codes if I can. They are a bad practice, and in my opinion, smell like spaghetti code.

I think it all boils down to how you use exceptions: if you use them like return codes (each method call in the stack catches and rethrows) then, yeah, they will be slow, because you have overhead each single catch/throw.

But if you throw at the bottom of the stack and catch at the top (you substitute a whole chain of return codes with one throw/catch), all costly operations are done once.

At the end of the day, they are a valid language feature.

Just to prove my point

Please run the code at this link (too big for an answer).

Results on my computer:

marco@<a href="#162001">sklivvz</a>:~/develop/test$ mono Exceptions.exe | grep PM
10/2/2008 2:53:32 PM
10/2/2008 2:53:42 PM
10/2/2008 2:53:52 PM

Timestamps are output at the beginning, between return codes and exceptions, at the end. It takes the same time in both cases. Note that you have to compile with optimizations.

Sklivvz
+2  A: 

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.

Quibblesome
+10  A: 

There is the definitive answer to this from the guy who implemented them - Chris Brumme. He wrote an excellent blog article about the subject (warning - its very long)(warning2 - its very well written, if you're a techie you'll read it to the end and then have to make up your hours after work :) )

The executive summary: they are slow. They are implemented as Win32 SEH exceptions, so some will even pass the ring 0 CPU boundary! Obviously in the real world, you'll be doing a lot of other work so the odd exception will not be noticed at all, but if you use them for program flow except your app to be hammered. This is another example of the MS marketing machine doing us a disservice. I recall one microsoftie telling us how they incurred absolutely zero overhead, which is complete tosh.

Chris gives a pertinent quote:

In fact, the CLR internally uses exceptions even in the unmanaged portions of the engine. However, there is a serious long term performance problem with exceptions and this must be factored into your decision.

gbjbaanb
+6  A: 

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.

Cory Foy
Nothing you have written contradicts the claim that exceptions are only slow if they're thrown. You've only talked about situations where they *are* thrown.When you've "significantly helped performance" by removing exceptions:1) Were they true error conditions, or just *user* error?
Jon Skeet
2) Were you running under the debugger, or not?
Jon Skeet
The only possible thing that you can do with an exception if not throwing it is create it as an object, which is meaningless. Being under the debugger or not doesn't matter - it is still going to be slower. Yes, there are hooks that will happen with a debugger attached, but it is still slow
Cory Foy
So Jon - I think what you are saying is that the occasional exception is no big deal. I agree with you. But in perf calls I did with large customers, we checked first for "debug" enabled in their web apps, and then how many exceptions they were throwing. It does matter.
Cory Foy
It's certainly slower than using a return code, but how much slower matters a lot. If throwing an exception takes a millisecond, then that occurring a few thousand times an hour doesn't matter. If it takes a second, it matters a lot!
Jon Skeet
How many exceptions *were* your customers throwing, btw? Don't forget that by default Response.Redirect throws an exception...
Jon Skeet
I know - I was part of the Premier team at MSFT. :) Let's just say, lots - thousands a second in some extreme cases we saw. Nothing like connecting with a live debugger and just seeing exceptions as fast as you could read. Ex's are slow - so is connecting to a DB, so you do it when it makes sense.
Cory Foy
Cory, I think the point of "only slow when they're thrown" is that you don't have to worry about performance because of the mere presence of catch/finally blocks. I.e. these in themselves don't cause a performance hit, only the occurrence of an actual exception instance.
Ian Horwill
+3  A: 

My XMPP server gained a major speed boost (sorry, no actual numbers, purely observational) after I consistently tried to prevent them from happening (such as checking if a socket is connected before try to read more data) and giving myself ways to avoid them (the mentioned TryX methods). That was with only about 50 active (chatting) virtual users.

Jonathan C Dickinson
Numbers would be useful, unfortunately :(Things like socket operations should vastly outweigh exception costs, certainly when not debugging. If you ever benchmark it fully, I'd be really interested to see the results.
Jon Skeet
A: 

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.

Drew Noakes
However, the presence of exceptions *can* impact optimization - methods with explicit exception handlers are harder to inline, and instruction reordering is limited by them.
Eamon Nerbonne
Good point about impacting inlining, Eamon!
Drew Noakes