Wednesday, April 6, 2011

Using multiples "usings", how this affect performance?

Hello,

I'm not against using "Using" statement, but I'm wondering how this affect performance when we use it inside one of another.

For example:

        using (test1 (type1))
        {
            using (test2(type2))
            {
                using (test2(type3))
                {
                }
            }
        }

This, will be translated in IL like this:

        try
        {
            try
            {
                try
                {
                }
                finally
                {
                }
            }
            finally
            {
            }
        }
        finally
        { 
        }

This will increase the size of assembly and, I believe, affect the performance of the application, right?

Shouldn't we use this?

        type1 test1 = new type1;
        type2 test2 = new type2;
        type3 test3 = new type3;

        try
        {

        }
        finally
        {
          test1.Dispose;
          test2.Dispose;
          test3.Dispose;
        }
From stackoverflow
  • A try/catch/finally is not expensive unless an exception is thrown. And even then several people (Jon Skeet included) have said that a thrown exception is not that expensive.

    In saying that, obviously you should not use exceptions for control flow.

  • No, don't use your second form. If test1.Dispose() throws an exception for some reason, test2.Dispose() and test3.Dispose() won't get called.

    The performance difference, if any, will be microscopic. Don't throw away correctness for insignificant performance :)

    Bruno Costa : Thanks, I didn't think on that ;).
    Gary Willoughby : >>Don't throw away correctness for insignificant performance. A thought for today!
    WACM161 : I totally agree see this article http://www.codinghorror.com/blog/archives/001218.html for another "microscopic optimization
  • I don't think worrying about the size of the assembly is something we typically need to worry about at the expense of writing more complicated to maintain code!

    Your example code shows exactly why we need the compiler to generate the code it does. If your call to new type2() fails then the Dispose method on test1 would never be called, which would cause a resource leak.

  • I think you're looking for the following:

    using (test1(type1))
    using (test2(type2))
    using (test3(type3))
    {
        // Code using test1/test2/test3 goes here.
    }
    

    It is equivalent to the first try-finally statement in your question, though clearly a lot more readable. Don't worry about the performance here really; it's good design practices and robust to use the nested method (as point out by previous posters), and additionally easily readable code (thanks to the multi-using statement) that count.

    Dan C. : This one will still expand to three try/finally blocks - which is correct as pointed out in the accepted answer. The obvious benefit is readability.
    Noldorin : Sorry, you're right. It does indeed expand to three try-finally blocks.

0 comments:

Post a Comment