Need to host a subversion repository? Try our hosted development tools.
Theme Graphic
Theme Graphic

The Official Programmer's Heaven Blog

The blog where the Programmer's Heaven team post stuff.

Subscribe

Author

Often knowledgable, sometimes wise, occasionally funny. The Programmer's Heaven blog team post about a whole range of topics, from practical advice on concurrency control to introductions to lesser known concepts such as functional programming. Don't forget to comment on the posts and let them know what you think, like and hate!

Archive

Tags

Posted on Tuesday, February 19, 2008 at 6:23 AM

Do try...catch blocks hurt runtime performance?

Recently, a friend mentioned that someone had told him that writing a try...catch block in C# (or substitute some other .Net language here) resulted in a "huge penalty" in terms of performance compared to if you had not written it. That is, merely writing such a block actually hurt program performance, even if an exception was never thrown. He didn't believe this was true, and rightly so - it's completely wrong. This post is a tidied up version of my explanation.

Inside a .Net Assembly

A .Net assembly, if we ignore various headers, consists of three things:
  • Bytecode: a sequence of low-level instructions that specify the body of a method
  • Metadata: a set of tables, a little bit like a database, describing higher level constructs such as classes, methods, signatures and so forth
  • Heaps: places where string constants and other such things are stored
That is, bytecode is what we actually execute and the rest is there to describe the extra details. To give you an example of the interplay between them, consider a method call. The bytecode stream contains the call instruction, followed by a method token, which is actually an index into the methods table. The methods table in turn allows us to find out where the bytecode for the method we're calling starts, so we can execute it.

(As an aside, these lookups wouldn't be all that expensive to do per call, though in reality they likely won't actually happen more than once per call site, unless it's done through reflection or a delegate. That's because when the CLR JIT-compiles the bytecode, it can compile the method call down to call instructions at the CPU level that refer directly to the method being called. You don't need to know this bit; it's just here for the curious.)

How Exception Handlers Are Stored

The .Net CLR has a concept known as a "protected region". A protected region is a sequence of instructions that has an associated handler. In C# or VB.NET, the instructions in a protected region correspond to code in a try block. There are various types of handlers, including typed ones (that catch only a certain type of exception) and finally ones. Note that a try...catch...finally will result in two protected regions at the CLR level, one for the catch and one for the finally. The protected regions will cover the exact same sequence of instructions, just have different handler addresses.

Each method that has protected regions comes with a table of them. For each protected region, it contains four entries:
  • The starting instruction in the bytecode for this protected region
  • The number of bytes worth of instructions from the starting point that are protected
  • The type of handler
  • The location in the bytecode of the handler
They are ordered with innermost handlers coming first.

What happens at runtime

Here is the important part when it comes to performance when an exception is not thrown. Since the protected regions are stored in a table and are not in the bytecode, and because the CLR does not need to worry about the exception handlers unless an exception is thrown, then there is no runtime penalty for having a try...catch block. For finally handlers it is a little different, because we do need to run those even when we don't have exceptions. However, since we can compute what we will need to run when statically, the JIT compiler can still emit code that jumps to the finally handler at the appropriate time, making the execution overhead of one of those most likely just a jump and a return.

So that's most of the answer to the question that was asked, but for interest let's take a look at what happens when an exception is thrown. Provided the current method has protected regions, you scan through the table to find if there are any that cover the instruction where the exception was thrown and that are capable of handling it (they are looking for an exception of the correct type, for example). If there are multiple nested handlers that could handle the exception, the ordering of innermost first means that we will find the correct handler.

If we find a handler, we execute it. If we don't find one, we move down to the next method in the call stack and check if it has a suitable handler, keeping going until we find one (or we discover that the exception is user-unhandled and terminate the program). This means that the cost of throwing and catching an exception is dependent on how far down the call stack you have to go to find a handler.

From this we can conclude that .Net is optimized for the case where you do not get exceptions. Since exceptions are intended to happen only in exceptional (that is, unexpected) circumstances, this is a sensible design decision. If you inclined to use exceptions for ordinary flow control, this should give you another reason not to.

And the cost of a try...catch block is...

So what can we conclude? The overall cost of a try...catch block that never handles an exception is a few bytes of memory - or at worst a few words - for the entry in the protected regions table. The only possible runtime penalty is the extra time to load those extra few bytes into memory. Since they are stored way away from the JITted bytecode stream, it's highly unlikely you're going to incur any additional cache-misses at runtime as a result of the handler too. Thus, the cost is essentially nothing.

The cost of not handling an exception that you should have may well be that your program crashes. This results in unhappy customers, a hit to your reputation and development time to go and do a bug-fix, which will almost certainly be much greater than if you had put it in there in the first place. Obviously, protecting code that can not throw an exception under any circumstances is a waste of your development time. But otherwise, it's best to be safe rather than sorry, safe in the knowledge that even if an exception never does occur in that bit of code, it's not really costing anything anyway.
Tags: .NET, C#, CLR, Exception
Bookmark: Submit To Digg Submit To reddit Submit To del.icio.us Bookmark With StumbleUpon Bookmark With FaceBook Bookmark With Google Bookmarks   Share: Share By Email By Email

13 comments on "Do try...catch blocks hurt runtime performance?"
Posted by Tom Gueth on Wednesday, February 20, 2008 at 2:41 PM
Image Of Author
okay but what is overhead of an exception
Honestly, always figured that a non-used try-catch block had little cost, or we would long ago have heard articles telling us to avoid them in code that must run uber fast.

Real question, is what is the cost in time of the "catch" when catch is in the same method, in one method removed, in second method removed, .... etc?
Posted by Matthew Noonan on Wednesday, February 20, 2008 at 7:54 PM
Image Of Author
Try/catch to set default values
It sounds like this is a message that got obscured through the grapevine. What it probably started out as, don't use try/catch for exceptions that can easily be avoided. The expensive cost of throwing an exception for an easily avoidable scenario, such as failing to check for null objects, that is something I see all the time in practice. Rather than simply wrap the offending code with an "if (obj == null)", they use the catch block to set a default value. That is the true cost of the try/catch: bad practices.
Posted by Thomas Danecker on Thursday, February 21, 2008 at 3:17 AM
Image Of Author
Missing one point
Yes, try...catch blocks do not hurt performance very much, but you forgot one performance-penalty: Optimization! The compiler (C# and JIT) can't do some optimizations it would be able to do when you don't use try..catch blocks. Though this optimizations don't hurt very much, it's a performance-penalty. Peter Ritchie has a blog post with an example: http://msmvps.com/blogs/peterritchie/archive/2007/06/22/performance-implications-of-try-catch-finally.aspx
Posted by Remy on Thursday, February 21, 2008 at 5:43 AM
Image Of Author
Maybe a C++ inheritance
In C++ Exceptions where expensive. Maybe that is why people think it's expensive in C# too.
Posted by Sephiroth on Thursday, February 21, 2008 at 9:19 PM
Image Of Author
Exceptions are not costly
I have been using try/catch in C++ for ages, and it has never slowed down anything. I did do a lot of testing when i started using it in C++ because I thought it might slow it down, but this was false. Maybe if I had some enormous exception handler, but that would slow down any language.

If try and catch don't slow down C++, I doubt it would slow down the .NET family unless Microsoft did something horribly wrong with the library!
Posted by Chinh Do on Tuesday, February 26, 2008 at 6:35 AM
Image Of Author
Try/catch can hurt performance
I think the general advice is to avoid using exceptions to implement normal program flow. One good example is to use DateTime.Parse and a try/catch block to determine if a date value is valid, instead of using DateTime.TryParse, which doesn't involve a try/catch block.

You are right that a stand alone try/catch block costs essentially nothing. However, like most performance issues, things don't become problems until they are used in a loop of some kind.

I ran a benchmark and posted the details here: http://www.chinhdo.com/20080226/try-catch-blocks-performance/.
Posted by http://vredit.wikido on Monday, May 12, 2008 at 4:25 PM
Image Of Author
http://vredit.wikidot.com/free-credit-report
http://vredit.wikidot.com/free-credit-report http://vredit.wikidot.com/free-annual-credit-report http://vredit.wikidot.com/free-credit-report-com http://vredit.wikidot.com/free-online-credit-report http://vredit.wikidot.com/my-free-credit-report http://vredit.wikidot.com/free-credit-report-on-line http://vredit.wikidot.com/free-credit-report-and-score http://vredit.wikidot.com/free-credit-report-government http://vredit.wikidot.com/free-credit-score-report http://vredit.wikidot.com/free-anual-credit-report http://vredit.wikidot.com/get-a-free-credit-report http://vredit.wikidot.com/www-free-credit-report-com http://vredit.wikidot.com/get-free-credit-report http://vredit.wikidot.com/free-yearly-credit-report http://vredit.wikidot.com/free-credit-reports http://vredit.wikidot.com/credit-report-for-free http://vredit.wikidot.com/experian-free-credit-report http://vredit.wikidot.com/free-annual-credit-report-com http://vredit.wikidot.com/free-credit-report-no-credit-card http://vredit.wikidot.com/free-credit-report-gov http://vredit.wikidot.com/free-copy-of-credit-report http://vredit.wikidot.com/free-instant-credit-report http://vredit.wikidot.com/free-credit-report-no-credit-card-required http://vredit.wikidot.com/totally-free-credit-report http://vredit.wikidot.com/free-annual-credit-reports http://vredit.wikidot.com/free-credit-reports-online http://vredit.wikidot.com/how-to-get-a-free-credit-report http://vredit.wikidot.com/my-free-credit-report-com http://vredit.wikidot.com/your-free-credit-report
Posted by sdf on Sunday, May 18, 2008 at 11:19 PM
Image Of Author
sdf
http://mortage.wikidot.com/mortgage-calculator http://mortage.wikidot.com/flash-mortgage-calculator http://mortage.wikidot.com/mortgage-calculator-plus http://mortage.wikidot.com/complete-mortgage-calculator http://mortage.wikidot.com/mortgage-calculator-com http://mortage.wikidot.com/www-mortgage-calculator http://mortage.wikidot.com/mortgage-calculator-for-website http://mortage.wikidot.com/mortgage-calculator-software http://mortage.wikidot.com/free-mortgage-calculator http://mortage.wikidot.com/c-mortgage-calculator http://mortage.wikidot.com/business-mortgage-calculator http://mortage.wikidot.com/mortgage-calculator-download http://mortage.wikidot.com/mortgage-calculators http://mortage.wikidot.com/free-mortgage-calculators http://mortage.wikidot.com/aol-mortgage-calculator http://mortage.wikidot.com/quick-mortgage-calculator http://mortage.wikidot.com/calc-mortgage http://mortage.wikidot.com/mortgage-calculator-html http://mortage.wikidot.com/calculate-your-mortgage http://mortage.wikidot.com/financial-mortgage-calculator http://mortage.wikidot.com/mortgage-calculator-new-york http://mortage.wikidot.com/easy-mortgage-calculator http://mortage.wikidot.com/mortgage-rates-calculator http://mortage.wikidot.com/calculator-for-mortgage http://mortage.wikidot.com/detailed-mortgage-calculator http://mortage.wikidot.com/canadian-mortgage-calculator http://mortage.wikidot.com/mortgage-finance-calculator http://mortage.wikidot.com/california-mortgage-calculator http://mortage.wikidot.com/mortgage-calculator-table http://mortage.wikidot.com/bi-weekly-mortgage-calculators

http://allrecipes.wikidot.com/recipe http://allrecipes.wikidot.com/chicken-recipe http://allrecipes.wikidot.com/salmon-recipe http://allrecipes.wikidot.com/recipes http://allrecipes.wikidot.com/chicken-recipes http://allrecipes.wikidot.com/all-recipes http://allrecipes.wikidot.com/cake-recipes http://allrecipes.wikidot.com/cheesecake-recipe http://allrecipes.wikidot.com/cookie-recipe http://allrecipes.wikidot.com/cake-recipe http://allrecipes.wikidot.com/smoothie-recipe http://allrecipes.wikidot.com/salad-recipes http://allrecipes.wikidot.com/food-recipes http://allrecipes.wikidot.com/drink-recipes http://allrecipes.wikidot.com/recipes-com http://allrecipes.wikidot.com/a-recipe http://allrecipes.wikidot.com/food-recipe http://allrecipes.wikidot.com/cookie-recipes http://allrecipes.wikidot.com/dessert-recipes http://allrecipes.wikidot.com/salsa-recipe http://allrecipes.wikidot.com/healthy-recipes http://allrecipes.wikidot.com/easy-recipes http://allrecipes.wikidot.com/pancake-recipe http://allrecipes.wikidot.com/cocktail-recipe http://allrecipes.wikidot.com/soup-recipes http://allrecipes.wikidot.com/salmon-recipes http://allrecipes.wikidot.com/chili-recipe http://allrecipes.wikidot.com/crock-pot-recipes http://allrecipes.wikidot.com/dinner-recipes http://allrecipes.wikidot.com/bread-recipes
Posted by Kennith Mann on Thursday, October 02, 2008 at 7:25 PM
Image Of Author
Context
In my experience, try/catch (even if the try isn't hit) does have a penalty, albeit not much.

For example, consider the following: You need to know if a a string is a valid DateTime. It was (foolishly) stored in the database as a string. It could be gibberish. Could be null. Could be partially complete. This application will be calling this request on over a million records(think about doing a migration).

Initially, I did try/catch before I realized I could do DateTime.TryParse.

In an effort to prove someone wrong, I wrote an app which did this. It initially had 10,000 string which 100% were perfect random date times.

I tried paring it with DateTime.TryParse, try/catch, and something else ( I forgot ).

The speed difference was a bit slower using try/catch, but it was very reasonable (the difference between 100ms and 173ms).

When I begin incrementing the percentage of bogus DateTimes, the penalty sky rocketed.

My conclusion, now, is that try/catches should only be used when you have little control of the environment. For example, when copying a file or deleting a file -- you will have potential network issues, security issues, etc that you can't calculate everything for (and even then, can still be open to a race condition).

I usually wrap my entire app in a try/catch, then database calls in a try/catch (and usually have a loop with a small delay, so it will try over and over again until the network comes back (it's a kiosk style application, not a regular one). I try really hard to avoid try/catches everywhere else.
Posted by Fai2012 on Wednesday, November 05, 2008 at 2:21 PM
Image Of Author
Quite costly in my case...
My VB.Net app. has a try/catch on each of the columns that it parses, for each row of a dataTable. The performance was nearly 1/10th when I took out the try/catch blocks, and did the error control in SQL itself. Laziness pays one way or the other, whether it's you or ones who have to look at your code later...
Posted by Francois Germain on Monday, November 17, 2008 at 9:36 AM
Image Of Author
Try Catch is costly when an exception is raised.
Try catch is expensive but only when you have an exception that is raised... Also for code that is ALWAYS JITted every time, the cost of Try/Catch is phenomenal...

One very important thing is to not write try/Catch/Throw in all your methods. This is going to slow down your application to a matter of 100% for each method that re-throws the error up above. I've seen that in some production system...

Use Try/Catch smartly only in top level functions or Events. Protect for Error instead of relying on try catch mechanism. Defensive programming is best. This is simple and in a high throughput web system, it will make a measurable difference.
Posted by Merlinox on Tuesday, June 09, 2009 at 2:07 AM
Image Of Author
Test speaks different
I've created a little test to see the performance difference between two simple functions with/without try/catch structure.

http://www.zshare.net/download/61136766b0db3bce/

9.12 seconds with try/catch vs 0.07 without.

May you explain it please???
Posted by Merlinox on Tuesday, June 09, 2009 at 2:22 AM
Image Of Author
Test speaks different (Errata Corrige)
Sorry I made an error in the project, and I forgot a line...

In a moltiplication loop of 1000000 times difference between with / without try/catch is only 20.81 ms (915.17 vs 849.36).

Correct project: http://www.zshare.net/download/6113733620ca12f6/

Leave A Comment
Subject:


Comment:
   Bold Italic Underline          Code Link Image Horizontal Rule


Because you do not have or are not logged in to your Programmer's Heaven account, please enter your name.

Name:


To help prevent comment SPAM, please enter the magic code '674' in the box:




Posting Rules
Please follow these rules when posting comments on blog posts.
  • Do not post anything that is racist, hate speech or of a sexual or adult nature.
  • Do not post or link to anything that infringes copyrighted laws.
  • Posting about security or legal topics is fine so long as you are not glorifying or encouraging people to perform illegal activities.
  • Both the author of this blog and the Programmer's Heaven administrators may delete any inappropriate comments without notice at their own discretion.
 
Popular resources and forums for programmers on Programmersheaven.com
Assembly, Basic, C, C#, C++, Delphi, Java, JavaScript, Pascal, Perl, PHP, Python, Ruby, Visual Basic
© Copyright 2009 Programmersheaven.com - All rights reserved.
Reproduction in whole or in part, in any form or medium without express written permission is prohibited.
Violators of this policy may be subject to legal action. Please read our Terms Of Use and Privacy Statement for more information.
Publisher: Lars Hagelin. Read the latest words from the publisher here.
Be the first to sign up for Lars Hagelin’s In-depth Outsourcing Newsletter here.
bootstrapLabs Logo A bootstrapLabs project.