Source

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.

with : , , ,