I know that exceptions have a performance penalty, and that it\'s generally more efficient to try and avoid exceptions than to drop a big try/catch around everything -- but
A common saying is that exceptions are expensive when they are caught - not thrown. This is because most of the exception metadata gathering (such as getting a stack trace etc.) only really happens on the try-catch side (not on the throw side).
Unwinding the stack is actually pretty quick - the CLR walks up the call stack and only pays heed to the finally blocks it finds; at no point in a pure try-finally block does the runtime attempt to 'complete' an exception (it's metadata etc.).
From what I remember, any try-catches with filters (such as "catch (FooException) {}") are just as expensive - even if they do not do anything with the exception.
I would venture to say that a method (call it CatchesAndRethrows) with the following block:
try
{
ThrowsAnException();
}
catch
{
throw;
}
Might result in a faster stack walk in a method - such as:
try
{
CatchesAndRethrows();
}
catch (Exception ex) // The runtime has already done most of the work.
{
// Some fancy logic
}
Some numbers:
With: 0.13905ms
Without: 0.096ms
Percent difference: 144%
Here is the benchmark I ran (remember, release mode - run without debug):
static void Main(string[] args)
{
Stopwatch withCatch = new Stopwatch();
Stopwatch withoutCatch = new Stopwatch();
int iterations = 20000;
for (int i = 0; i < iterations; i++)
{
if (i % 100 == 0)
{
Console.Write("{0}%", 100 * i / iterations);
Console.CursorLeft = 0;
Console.CursorTop = 0;
}
CatchIt(withCatch, withoutCatch);
}
Console.WriteLine("With: {0}ms", ((float)(withCatch.ElapsedMilliseconds)) / iterations);
Console.WriteLine("Without: {0}ms", ((float)(withoutCatch.ElapsedMilliseconds)) / iterations);
Console.WriteLine("Percent difference: {0}%", 100 * withCatch.ElapsedMilliseconds / withoutCatch.ElapsedMilliseconds);
Console.ReadKey(true);
}
static void CatchIt(Stopwatch withCatch, Stopwatch withoutCatch)
{
withCatch.Start();
try
{
FinallyIt(withoutCatch);
}
catch
{
}
withCatch.Stop();
}
static void FinallyIt(Stopwatch withoutCatch)
{
try
{
withoutCatch.Start();
ThrowIt(withoutCatch);
}
finally
{
withoutCatch.Stop();
}
}
private static void ThrowIt(Stopwatch withoutCatch)
{
throw new NotImplementedException();
}