How slow are .NET exceptions?
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 inappropriate 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.
Why is throwing exceptions so slow?
Exception handling requires some complexity and "magic". Seconding @Joni's response a major cost is gathering the stack trace. When an exception is thrown, the run time has to walk down the stack's activation records looking for a compatible exception handler, executing finally blocks each step of the way. All this has to occur at run time; it can't be fixed up by the compiler. In languages like C++ destructors have to be executed.
Exception processing is essentially an out of band "exceptional" processing mode. Things that speed up normal execution such as caching don't work as well. (I would imagine locality-of-reference is a lot worse here). This processing could be optimized, but since exc handing is supposed to be "special" it's given less attention.
C# performance cost of exceptions
Use Dictionary.TryGetValue
to avoid exceptions in your example code at all. The most expensive part is the try .. catch
.
If you cannot get away from exceptions then you should use a different pattern to perform actions inside a loop.
Instead of
for ( i = 0; i < 100; i++ )
try
{
DoSomethingThatMaybeThrowException();
}
catch (Exception)
{
// igrnore or handle
}
which will set up the try .. catch
for every step whether an exception has raised or not, use
int i = 0;
while ( i < 100 )
try
{
while( i < 100 )
{
DoSomethingThatMaybeThrowException();
i++;
}
}
catch ( Exception )
{
// ignore or handle
i++;
}
which will only set up a new try .. catch
when an exception was thrown.
BTW
I cannot reproduce that massive slowdown of your code as you describe. .net fiddle
.NET Exception And Performance
Well, because it does something. Doing anything takes time.
Throwing an exception creates an object, obtains a copy of the stack, walks the stack up to two times, and perhaps marshals across domains. Doing stuff takes time. In an ideal world it will also be the branch that wasn't predicted as being taken (because it should be the branch that was less likely) though I've no idea if that's the case or not. It's also particularly likely to lead to cases where the caches are being refilled because control has moved to somewhere "far away".
All that said though, exceptions aren't particularly slow except when being run in a debugger (which for obvious reasons does more work again when an exception is thrown). It's slow enough that doing try-and-catch in a loop where doing test-and-try or tryparse-and-report makes more sense is a bad idea, but these fall into the category of good micro-optimisations ("micro-optimisation" is often used as a slur, but when the approach that's semantically clearer is also slightly more performant then it's a good thing for the reason of that clarity - it's when we make things less clear and semantically sensible for the sake of a few cycles that "micro-optimisation" becomes a negative).
Do try/catch blocks hurt performance when exceptions are not thrown?
Check it.
static public void Main(string[] args)
{
Stopwatch w = new Stopwatch();
double d = 0;
w.Start();
for (int i = 0; i < 10000000; i++)
{
try
{
d = Math.Sin(1);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
w.Stop();
Console.WriteLine(w.Elapsed);
w.Reset();
w.Start();
for (int i = 0; i < 10000000; i++)
{
d = Math.Sin(1);
}
w.Stop();
Console.WriteLine(w.Elapsed);
}
Output:
00:00:00.4269033 // with try/catch
00:00:00.4260383 // without.
In milliseconds:
449
416
New code:
for (int j = 0; j < 10; j++)
{
Stopwatch w = new Stopwatch();
double d = 0;
w.Start();
for (int i = 0; i < 10000000; i++)
{
try
{
d = Math.Sin(d);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
finally
{
d = Math.Sin(d);
}
}
w.Stop();
Console.Write(" try/catch/finally: ");
Console.WriteLine(w.ElapsedMilliseconds);
w.Reset();
d = 0;
w.Start();
for (int i = 0; i < 10000000; i++)
{
d = Math.Sin(d);
d = Math.Sin(d);
}
w.Stop();
Console.Write("No try/catch/finally: ");
Console.WriteLine(w.ElapsedMilliseconds);
Console.WriteLine();
}
New results:
try/catch/finally: 382
No try/catch/finally: 332
try/catch/finally: 375
No try/catch/finally: 332
try/catch/finally: 376
No try/catch/finally: 333
try/catch/finally: 375
No try/catch/finally: 330
try/catch/finally: 373
No try/catch/finally: 329
try/catch/finally: 373
No try/catch/finally: 330
try/catch/finally: 373
No try/catch/finally: 352
try/catch/finally: 374
No try/catch/finally: 331
try/catch/finally: 380
No try/catch/finally: 329
try/catch/finally: 374
No try/catch/finally: 334
Exception handling. How long does catch take?
Exceptions are slower than all other program flow but not to the extent they should be avoided for performance reasons. However, they are not meant to be used for program flow. In your situation, you have a very valid alternative that is better than using exceptions. When you can predict a situation and handle it appropriately without exceptions, always do that. Also, don't use exceptions in normal program flow as a convenience.
Use exceptions when you have an unanticipated exceptional situation you can't handle directly.
Related Topics
How to Check For Internet Connectivity Using .Net
Why Use the 'Ref' Keyword When Passing an Object
Odbcconnection Returning Chinese Characters as ""
How to Evaluate a C# Expression Dynamically
How to Divide Two Integers to Get a Double
Calculate Md5 Checksum For a File
Selenium C# Webdriver: Wait Until Element Is Present
How to Remove Duplicates from a C# Array
Pass Array Parameter in Sqlcommand
Hresult: 0X800A03Ec on Worksheet.Range
Is It Better to Return Null or Empty Collection
How to Enable C# 6.0 Feature in Visual Studio 2013
How to Easily Check If Access Is Denied For a File in .Net