Performance Implications of try/catch/finally

The accepted wisdom regarding performance of try/catch|finally in C# has normally been: try has no performance side-effects unless an exception is thrown.

A discussion I was involved in recently caused me to discover some performance implications of try/catch blocks. The discussion revolved around protecting the volatility of certain members and the cross-thread memory ordering rules during run-time and during just-in-time compilation.  As it turns out, Microsoft’s x86 .NET 2.0 just-in-time compiler disables optimizations that would affect the CIL order of read/writes in protected blocks (AKA “protected regions”, “guarded blocks”, or “try blocks”).  As a result no optimizations are performed in try blocks.

As it turns out, there are performance side-effects to try/catch even if no exceptions are thrown.  In the following academic example:

    int count = 1;
    SomeMethod();
    count++;
    SomeOtherMethod();
    count++;
    Console.WriteLine(count);

The x86 just-in-time compiler will effectively optimize this as follows:

    SomeMethod();
    SomeOtherMethod();
    Console.WriteLine(3);

The end-result is the same but the side-effects (that would normally be only visible in a debugger) are different (e.g. count never has the value 2).  The just-in-time compiler can do this because it knows no other code can see count when it has the value 2.

Now, wrapping this in a try block, as follows:

    int count = 1;
    try
    {
        SomeMethod();
        count++;
        SomeOtherMethod();
        count++;
    }
    finally
    {
        Console.WriteLine(count);
    }

...is not optimized.  count will be created, it will have the value 1, it will have the value 2 after the call to SomeMethod, it will have the value 3 after SomeOther method, and will have the value 3 when Console.WriteLine is called.  There are two increments that therefore must be performed that are a waste of cycles.

So, be careful how you write code in try blocks.

Published Friday, June 22, 2007 12:38 PM by PeterRitchie

Comments

# re: Performance Implications of try/catch/finally

As always excellent tidbit.  I've been reading your blog and reading your e-mails on Developmentor's .NET lists and I must say I learn from you every week.  Thanks for keeping it interesting and keep up the good work :)

Friday, June 22, 2007 4:21 PM by Peter (Not Richie)

# re: Performance Implications of try/catch/finally

Is the effect, loss of optimization, the same if you move the scope of the try/catch to an outside method calling a function which has the code...or at what point, if any does, optimization come back into play?

Friday, June 22, 2007 8:15 PM by OmegaMan

# re: Performance Implications of try/catch/finally

@OmegaMan: I'm finding it's not as cut-and-dry as "no optimizations are performed".  To a certain extent it depends on what is and isn't in the try block.  It appears a more accurate statement would be "no optimizations are performed that would affect reordering of reads/writes of variables used inside AND outside the try block"; but, I'm following up on that.

Saturday, June 23, 2007 9:26 AM by PeterRitchie

# Performance Implications of try/catch/finally, Part Two

In a previous blog entry Performance Implications of try/catch/finally I outlined that the conventional

Friday, July 13, 2007 10:44 AM by Peter Ritchie's MVP Blog

# Exception Logging

There is often a requirement for an application to log unhandled (and sometimes "handled")

Wednesday, August 01, 2007 9:52 PM by Peter Ritchie's MVP Blog

# re: Performance Implications of try/catch/finally

Does this mean that locked code is not optomized? e.g:

Lock(this)

{

   SomeMethod();

   count++;

   SomeOtherMethod();

   count++;

   Console.WriteLine(count);

}

Wednesday, January 16, 2008 2:00 PM by Jesse

# re: Performance Implications of try/catch/finally

Yes, lock uses try/catch, it will have the same performance implications.

Wednesday, January 16, 2008 8:22 PM by PeterRitchie

Leave a Comment

(required) 
(required) 
(optional)
(required)