Chinh Do

Try/Catch Blocks Can Hurt Performance

26th February 2008

Try/Catch Blocks Can Hurt Performance

Over at Programmers Heaven.com, there’s an interesting article on the potential performance impact of try/catch blocks. The article concluded that the average cost of a try/catch block is essentially nothing (sorry there’s no author information on the post so I couldn’t tell who wrote it), and that .NET/C# programmers should not think twice about using try/catch blocks.

The author is right that a try/catch block has essentially zero cost. However, like most coding performance issues, exceptions and try/catch blocks do not have performance implications until they occur in some type of loop. Something like this will do the job:

Dictionary<int, int> numbers = new Dictionary<int, int>();
Stopwatch w = new Stopwatch();
w.Start();
int notFound = 0;
for (int i = 1; i <= 1000000; i++)
{
    try
    {
        int value = numbers[i];
    }
    catch (KeyNotFoundException)
    {
        notFound++;
    }
}

w.Stop();
Console.WriteLine(notFound);
Console.WriteLine("Elapsed: " + w.ElapsedMilliseconds + ".");

In the block of code above, I am trying to find the number of integers from 1 to 1,000,000 that are not in the numbers dictionary. One way to do it is to try to access the dictionary item by key. Since the Dictionary class will throw a KeyNotFoundException if the key is not found, that’s how I am going to know whether each value is in the dictionary or not.

Well, let’s just see how long that code takes to run. On my virtual PC it took … hold on a sec, it’s till running… still waiting… not quite there yet… finally: 101031 (101 seconds).

If you have any doubt, this is the type of try/catch block or exception handling they advice against. :-)

The above logic, when implemented correctly without using a try/catch block, took only 10 milliseconds. Yes, that’s not a typo: 10 milliseconds. Oh, only about 10,000 times faster.

Here’s the correct code:

Dictionary<int, int> numbers = new Dictionary<int, int>();

Stopwatch w = new Stopwatch();
w.Start();

int notFound = 0;
for (int i = 1; i <= 1000000; i++)
{
    if (! numbers.ContainsKey(i))
    {
        notFound++;
    }
}

w.Stop();
Console.WriteLine(notFound);
Console.WriteLine("Elapsed: " + w.ElapsedMilliseconds + ".");

So, do consider performance impact when using exceptions and try/catch blocks. Avoid using exception handling to implement normal program flow. Here are some links on exception handling best practices in .NET:

kick it on DotNetKicks.com

This entry was posted on Tuesday, February 26th, 2008 at 1:38 am and is filed under Dotnet/.NET - C#, Programming. You can follow any responses to this entry through the RSS 2.0 feed. Both comments and pings are currently closed.

There are currently 28 responses to “Try/Catch Blocks Can Hurt Performance”

  1. 1 On February 26th, 2008, Tim B said:

    I think you somewhat misunderstood the article you linked to. The author is saying that there is a penalty if the program flow enters the catch block (even without a loop), but that **the existence of a try/catch block itself does not inherently affect performance**. In the article summary: “The overall cost of a try…catch block that never handles an exception is a few bytes of memory”. That said, you are correct that regularly handling an exception within a loop will have horrific effects on performance. The safest code would probably include a try/catch around the entire loop in your final example.

  2. 2 On February 26th, 2008, X4lldux said:

    Yeah, you’re right, but writing code in the 1 style is just crap and should not be doing! So essentially exceptions are zero cost but when they occur they are huge performance drop down. But when shit happens performance isn’t really the case.

  3. 3 On February 26th, 2008, Darrell said:

    Shouldn’t the correct example be

    if (!numbers.ContainsKey(i))
    {
    notFound++;
    }

    While I agree with the core message of being aware of the performance impact of try..catch I think the code example is not necessarily the best. It seems like just a poor programming example.

  4. 4 On February 26th, 2008, Chinh Do said:

    Thanks for everyone’s comments.

    My example is a little bit on the extreme side but it’s to prove a point: that bad/incorrect use of structured exception handling CAN lead to performance problems.

    The Programmers Heaven article does say in its conclusion that the performance hit of a try/catch block that never handles an exception is virtually nothing. I totally agree with that.

    However, by virtue of having a try/catch block, there is the possibility that it WILL catch and handle an exception :-). I also think that many programmers will read the PH article and come out with the wrong conclusion that they should never worry about performance issues with exception handling.

    Darrell: Thanks for pointing out the typo in my code. Corrected.

  5. 5 On February 26th, 2008, Wesner Moise said:

    “Structured exception handling” refers to a specific Win32 OS feature, not the .NET feature…

    There is no cost to using try/catch within loops or anywhere else, other than the loss of inlining opportunities.

    Costs only arise when exceptions are raised. As a general rule, you should not be relying on exceptions for normal programming tasks. Exceptions are generally for exceptional events, and take up orders of magnitude even outside loops because of stack walking and a variety of other activities.

    You had multiple options that avoided the use of exceptions:
    1) Use TryGetValue
    2) Use ContainsKey

  6. 6 On February 26th, 2008, Chinh Do said:

    Wesner: I am sure “structured exception handling” can be used to refer generically to the try/catch exception handling syntax. Here are some examples from Microsoft: Examples: http://support.microsoft.com/kb/816157, http://support.microsoft.com/kb/315965, Intro to Structured Exception Handling.

    I agree with your other points. Bad/inappropriate use of exception handling can lead to performance issues and should be avoided.

  7. 7 On February 27th, 2008, Reflective Perspective - Chris Alcock » The Morning Brew #41 said:

    [...] Try/Catch Blocks Can Hurt Performance Significantly – The Try/Catch performance debate continues… [...]

  8. 8 On February 27th, 2008, James Curran said:

    Ok, I’m ignoring the entire point of the article, but ….isn’t the actual “correct” method:

    int notused = 1000000 – numbers.Count;

    Yes, using exceptions for non-exception occurences is bad. Dumb algorithms are just as bad.

  9. 9 On February 27th, 2008, Chinh Do said:

    James:

    I guess I could have done a better job explaining the code example. Perhaps a comment here and there would have helped.

    My point was not to demonstrate good/realistic algorithm, but to highlight the fact that bad exception handling practice can potentially be harmful to your performance. If it helped, please pretend that the Dictionary is passed to you from somewhere else. I don’t think anybody would write real code like that.

    Nice alternate algorithm though.

  10. 10 On March 14th, 2008, ovation said:

    Chinh,

    This is a great example, bah on the nay-sayers. We are smart enough to know what you mean. Thanks for showing how some simple design decisions and checking can enhance performance!

    Keep up the good work, love the blog!

    -brian

  11. 11 On April 16th, 2008, Milivoj Savin said:

    James,

    Your answer only works if you know that all your keys are all in the range 1 to 1000000. What if the container has a key of 1000001 in it? Can’t Count that.

  12. 12 On June 20th, 2008, Luís Soares said:

    Wouldn’t be faster to get the list of keys and only iterate on them?

  13. 13 On September 15th, 2008, tommy said:

    wouldn’t it just be faster to not do any of that code? Seems like if you skipped it all you could just avoid all the code and exceptions in the first place :)

  14. 14 On September 17th, 2008, Chinh Do said:

    Tommy: Yes you are 100% right. My code example is not a very good one.

  15. 15 On November 19th, 2008, chinhdo said:

    #http://www.chinhdo.com/wp-includes/images/smilies/icon_smile.gif

    posted on September 15th, 2008 at 12:21 am
    # 14 On September 17th, 2008, Chinh Do said:

    Tommy: Yes you are 100% right. My code example is not a very good one.

  16. 16 On February 4th, 2009, Andrew Ross said:

    I came to this article after looking at the article from programmers heaven, looking to see if I should bother rewriting the search code for an application I have just inherited.

    I was going to leave it as it was after seeing the programmers heaven article.
    I didn’t like the try catches everywhere but I thought it wasn’t going to hurt so why bother. After seeing this article I’ll get to removing the try catches and just check to see if the row number exists.

    Worst part is the methods that I’m going to rewrite are used in a loop.

    Thanks for clearing that up.

  17. 17 On February 4th, 2009, Chinh Do said:

    Andrew:

    I do not by any means recommend that try/catch blocks are avoided. I just wanted to stress that there IS a cost when an exception is raised. The programmers heaven article actually stated that as well.

    Since you have a loop involved with your exception handling code, I think you are right to re-examine the exception handling code. I would carefully examine any possibility that the exception handling code may get triggered repeatedly. There’s really the only scenario where your performance can be degraded significantly.

    Chinh

  18. 18 On August 26th, 2009, thedudeewr said:

    sorry but while you might be true , youre not comparing apples to apples, you should take a class in algorithm analisys. the question is wheter ONE try catch hurts performance (and some memory) , and the article you linked answers this, only adds a litle more to memory and performance, if you insert it in a loop then u multiply this by n so then the algorithm goes to O(n), to prove your point you will have get as result a O(n^2) or higher to make your point.
    what you are saying is like comparing creating one integer as opposed to creating integers inside a loop. but anyway good try.

  19. 19 On August 26th, 2009, Chinh Do said:

    Hi thedudeewr: Thanks for you comment. The point of the ProgrammerHeaven article is absolutely correct… there’s no significant performance issue with one single empty try/catch block.

    My main point was only to add “but be careful”… even if the empty try/catch block doesn’t impose any performance issue, we usually have some type of code inside the catch block… and that code may be an issue when it gets triggered, especially in a loop. That’s all.

    Anyway, I guess I didn’t say what I wanted to say clearly. I can see how my post could be misunderstood as trying to refute the ProgrammerHeaven’s article.

  20. 20 On December 15th, 2009, Dmitriy said:

    This is would be the best way to do this try catch block
    w.Start();
    int notFound = 0;
    try
    {
    for (int i = 1; i <= 1000000; i++)
    {
    int value = numbers[i];
    }
    }
    catch
    {
    notFound++;
    }
    this.label1.Text = “Elapsed: ” + w.ElapsedMilliseconds + “.”;

  21. 21 On February 6th, 2010, Derk said:

    The thing that I see missing in this discussion is that exceptions should only be used for _exceptional_ behaviour. In your example, Chinh, you’ve used exceptions for expected behaviour. In general, exceptions are a great thing, and they don’t affect performance. Just don’t write code that depends on them being called.

  22. 22 On February 6th, 2010, Chinh Do said:

    Hi Derk: Thanks for your comment. I agree with you. My example is an example of bad exception handling, so definitely don’t do it like that. Chinh

  23. 23 On April 6th, 2010, Using JavaScript’s Try-Catch Statement | Impressive Webs Toronto said:

    [...] short answer seems to be yes, although this article on MSDN says that performance is affected only when the catch portion [...]

  24. 24 On April 8th, 2010, Using JavaScript’s Try-Catch Statement | 610 Design said:

    [...] short answer seems to be yes, although this article on MSDN says that performance is affected only when the catch portion [...]

  25. 25 On June 19th, 2010, [Перевод] Лучшие практические решения обработки исключений в веб-приложениях ASP.NET - Александр Гончарук - технический блог - Microsoft User Group Винн said:

    [...] Try/Catch Blocks Can Hurt Performance Significantly – Chinh Do [...]

  26. 26 On October 1st, 2010, Ian said:

    If you are for example iterating a list of 100,000 items, and out of that list, perhaps you may encounter 1 or exception situations, would it be more performant to do an if check 100,000 times, or to remove the if check, and allow your exception block to handle the ‘exceptional situation’, say perhaps a null reference or something?

  27. 27 On November 14th, 2010, Boigohegeapem said:

    KamaSutra Intensity Condoms KamaSutra Intensity Condoms 7 stiff neck side effect cymbalta how to buy Eulexin prescription 6 medications augmentin long term Aricept Aricept 5 combining wellbutrin and lexapro buy cheap Avapro 6 caffeine hyperactivity generic Betnovate fedex 4 viagra 100mg tablets purchase Lisinopril online 5 imitrex interaction buy Levaquin online without a prescription 3 glyburide micro 3m generic Glyset online canada 7 who makes lithium carbonate online us pharmacy Emsam 6 blackburn bike light lithium x8 Hytrin saturday delivery 2 symptom relief and bactrim
    cheapest prices for Advair Diskus online 2 lasix and potassium online Kamagra Oral Jelly sales 3 ganeric viagra how to buy Eulexin prescription 6 mood stabilizers depakote Indocin overnight 5 tropical ketoconazole cream Keppra cheap cod 5 spontaneious orgasm paxil Allopurinol cheap next day 8 how to dispense clonidine for toddler Coreg without presciption 1 aciphex for heartburn Grifulvin V drug 4 side effects of cefuroxime axetil non prescription Furosemide alternative 9 topamax assistance program buying Citalopram 2 effect of finasteride

  28. 28 On December 24th, 2010, Jarmo said:

    I was curious about try-catch penalty, and I found this page, but it did not clearly told me is there a penalty or not. I wrote code to prove.

    System.DateTime start = System.DateTime.Now;
    // 100 million times
    for( int index = 0; index < 100000000; ++index)
    {
    try
    {
    int x = index;
    }
    catch( System.Exception )
    {
    }
    finally { }
    }
    System.DateTime end = System.DateTime.Now;
    double elapsed = (end – start).TotalMilliseconds;

    250ms without try-catch-finally
    484ms with try-catch
    875ms with try-catch-finally
    750ms with try-finally

    I can now relax and write try-catch. Of course I use it only for exceptions, which occur seldomly.