Try..Catch blocks always expensive?

13,267

Solution 1

In general, in today's implementations, entering a try block is not expensive at all (this was not always true). However, throwing and handling an exception is usually a relatively expensive operation. So, exceptions should normally be used for exceptional events, not normal flow control.

Performance is only one factor to consider, though, especially in the modern world. If (for instance) you're doing something once in response to a user action, it probably doesn't matter from a performance standpoint whether you use an exception even when you could have done a proactive check instead, provided the exception happens quickly enough the user isn't jolted.¹ But if you're doing something in a tight loop that's going to run hundreds of thousands of times, or you're writing a web application that may need to handle a huge load, you'd probably want to avoid using an exception for a normal case.


¹ More than a decade ago I was responsible for enhancements to a .Net 1.1 "no touch deployment" application in which the first exception thrown took fully three seconds. This was a sufficient problem in one use case involving opening a file the user had asked for which might reasonably not be there that I had to add a check for file existence prior to trying to open the file, which is normally poor programming practice (just try to open the file and handle the exception if that fails), purely because the user experience waiting for that exception to get built was so poor. But that's probably not the world we live in now.

Solution 2

They are pretty cheap unless there is an exception. So you should avoid them when an exception is expected, as in your example above.

I think exceptions on bad user input are generally unwise. Exceptions on out of memory or other unexpected failures are fine.

Solution 3

Just to play devils advocate - I have found a great use for using Exceptions for flow control: The 'cancel' button.

If you have a function running on some service that may take 10-120 minutes, which is doing a bunch of different things, I've found that doing if(hasCanceled) throw new JobCancelledException() inside of my Log() function (which logs at each step that I'm at) to work just friggan awesome. It bails out of the current execution of code and stops running the job - exactly what I need. I'm sure there's some better way to do it, maybe somehow using events - but for my case it works great (especially since jobs are not regularly cancelled).

Other then that though - I'm 100% in agreement that Exceptions should never be used as a flow control tool..

@Kornel - I have two words for that post... Holy $hit =)

here's a simple pseudo code sample:

Class Job
{
       Public Run(param1,param2,etc...)
       {
             Try
            {
                   Log("Doing Something")
                   DoSomething()

                         Log("Doing Another")
                         DoAnother()

                         Log("This keeps going, etc, inside of these function we make the same Log calls where it makes sense")
                         Etc()
                   }
                   Catch(JobCancelledException)
                   {
                        status="Cancelled"
                   }
            }

              Private Log(ByVal str As String)
              {
                      MessateToUser(str)

                      if(hasCancelled)
                          throw new JobCancelledException
            }

             private SomeEvent_WhenUserPushesCancelButton()
             {
                       hasCancelled=True
             }
}

Solution 4

The overhead of the try block is very low, so if no exception is thrown then there should be no noticeable penalty. The main overhead that occurs when an exception is thrown is the stack walk that takes place looking for a handler - since you are caching the exception so close to the source, I doubt there will be much of a performance issue. Ideally though you would be able to validate your inputs properly beforehand, but email validation is fairly complicated so it may well not be worth it in this case.

Solution 5

Exceptions are only expensive if an exception is thrown. I'm sure there is some very minimal cost to setting up up a Try..Catch block but it is by far outweighed by the cost of not catching the exception at all and having your program crash. As others have pointed out, Try..Catch blocks should only be used for exceptional circumstances.

Share:
13,267

Related videos on Youtube

Skoder
Author by

Skoder

Updated on April 15, 2022

Comments

  • Skoder
    Skoder about 2 years

    Possible Duplicate:
    Do try/catch blocks hurt performance when exceptions are not thrown?

    Hey everyone, Just a quick question about try..catch blocks. I've heard they're expensive to use and shouldn't be used as part of a program's flow. However, in order to validate email addresses, I'm using the following code.

            try
            {
                MailAddress checkEmail = new MailAddress(testEmail);
    
                return true;
            }
            catch
            {
                return false;
            }
    

    Due to prior validation, I don't many exceptions to be caught unless it's an attempt to bypass validation. My question is, are Try...Catch blocks only expensive if an exception is caught, or is it always expensive regardless of whether any exception is thrown?

    Thanks

    EDIT : Thanks for all the replies. I've decided that since the checking (in C#) isn't very expensive, I'll stick with this method. It's mainly because an actual exception being thrown is rare since there are prior validation steps that ensure no one accidentally enters an invalid email address.

    • Eric Lippert
      Eric Lippert over 14 years
      You say that the exception should never happen, and if it does, it is the result of someone attempting to bypass your security mechanisms. Does it seem wise to eat the exception and continue blithely along, now that you know that there's an attacker loose in the system? I would let the exception bubble up to the caller and halt the program. When you notice that there's a hostile guy with an axe who has bypassed your building security and he sets off an alarm, you let the alarm ring and summon security; you don't automatically turn off the alarm!
    • Skoder
      Skoder over 14 years
      Hi Eric. My actual code is significantly larger than this. It monitors the user, logs data and blocks access. I simply showed an example call I was making to see whether or not it was an efficient way of doing things :)
    • Kobi
      Kobi over 14 years
      See also this question: stackoverflow.com/questions/1308432/…
    • Marc Gravell
      Marc Gravell over 14 years
      @Eric - fantastic quote - made me smile, thanks.
    • TheVillageIdiot
      TheVillageIdiot over 14 years
      remember @Skider "security is an illusion"
  • Skoder
    Skoder over 14 years
    Hi, sorry I thought I tagged C#. I've fixed it now. I only expect the exception to be thrown if a user has purposely tampered with the POST header since standard validation is applied on the input.
  • Skoder
    Skoder over 14 years
    The input is validated normally using regular expressions. However, if someone has purposely bypassed the validation (by tampering the POST header), this exception is potentially thrown.
  • Skoder
    Skoder over 14 years
    Thanks. I'm using C# (I've fixed the tag). I assume that it's a similar thing in C# as it is in Java. I am using a pre-validated email address to ensure integrity, but this is always called regardless.
  • John Knoeller
    John Knoeller over 14 years
    It's a judgement call. But I'd say that's sufficiently exceptional.
  • Jason Snelders
    Jason Snelders over 14 years
    Very nicely put answer @T.J. I'd also add with regard to the performance hit when handling an exception, don't forget that at that point the application has stopped behaving as expected (i.e. the proverbials have hit the fan), indicating a bigger issue that needs to be resolved, therefore performance probably isn't such a big concern at that point. This of course follows T.J.'s point of "exceptions should only be used for exceptional events" - something I still find many developers don't appreciate.
  • dsimcha
    dsimcha over 14 years
    Since when is opening a file a performance-critical operation? IMHO try-catch is more readable in this case and the performance difference is negligible compared to the overall complexity of the operation.
  • T.J. Crowder
    T.J. Crowder over 14 years
    @dsimcha: That's fine, although if you find simple if statements hard to read... ;-) I've worked with frameworks where an exception (the first exception of a given type) would cause 2-3 second pauses resulting in a degraded user experience; opening a local file is a dramatically sub-second operation.
  • dsimcha
    dsimcha over 14 years
    @T.J. Crowder: What kind of horribly defective framework would make it take this long to create an exception? Yes, exceptions are slow, but I thought slow meant on the order of tens or hundreds of thousands of CPU cycles, not billions (assuming modern hardware).
  • T.J. Crowder
    T.J. Crowder over 14 years
    @dsimcha: That particular example was a .Net 1.1 "rich web client;" thankfully we finally got that customer upgraded to something more recent. Happened both when run via NTD and as a local executable. But leaving that aside, for user-supplied paths I'd definitely check before opening (whereas I don't if the code should be able to expect it to be there), since one of the normal cases is that the file is not there; otherwise, maintenance coders have to go scrolling down and point through your exception-handling code to find out what you do for this (to my mind) non-exceptional condition.
  • dferraro
    dferraro over 14 years
    It's a way to implement the 'cancel' button / functionality of some job that a user can execute. This job can take hours to run given the right params. I Log() at each different step anyway to give user feedback. So each time I log, I check a hasCancelled field and if it's true, I throw a JobCancelledException. Now, no matter where we are in the code, the job will stop immediately, as I handle this exception at the highest level of the call stack. Super simple and works great.
  • Boris Yankov
    Boris Yankov over 12 years
    Never? Never ever? Even if you deeply understand what is going on? And if like in the current case, it is an easy, effective and bug free way to do something otherwise hard to do? (-1 for no effort to distinguish current case to the general principle).
  • Kornel Kisielewicz
    Kornel Kisielewicz over 12 years
    @Boris, especially if ran in a loop of 1 million iterations.