Share via


The Dangers Of Exception Based Logic Part 1 - Parsing Integers

Exception based logic is one of those things that actually makes me cringe when I see it.  Often times it is really easy to avoid like in the case below.  Believe it or not, exceptions in .NET aren't cheap and shouldn't be taken for granted.

 

Exception Based Logic:     14-19ms

Try Function Based Logic: 0ms

 

 static void Main(string[] args)
{
    using (new QuickTimer("Exception Based Logic"))
    {
         for (int i = 0; i < 10; i++)
         {
             try
             {
                 int j = Int32.Parse("a");
             } catch (Exception ex)
             {
                 Console.WriteLine("Error");
             }
         }
    }

    using (new QuickTimer("Try Function Based Logic"))
    {
         for (int i = 0; i < 10; i++)
         {
              int j = 0;
              if (!Int32.TryParse("a",out j))
              {
                  Console.WriteLine("Error");
              }
         }
      }
}

Comments

  • Anonymous
    March 03, 2008
    instead of what you have above, what abouttry{  int j = Int32.Parse("a");}catch{  Console.WriteLine("Error");}without passing the exception, is that as expensive?
  • Anonymous
    March 03, 2008
    I don't see any speed difference whether I pass the exception or not.  I would think since I don't use the exception the compiler just optimizes it out.  
  • Anonymous
    March 03, 2008
    I'd doubt the compiler performs that sort of optimization, especially in this case, where the code that's creating and throwing the exception exists in a library that's already been compiled to MSIL.  In this scenario, the only possible player that could optimize anything would be the JIT, and the JIT has no way of knowing whether every call the program will make to the method will result in the exception object being ignored, since the JIT doesn't have an overall picture of the program, only what needs to be compiled right now, and some information about what's been compiled in the past.Plus there's the what-ifs -- What if the construction of the exception object has side effects? Optimizing the exception away would change the meaning of the code.  What if someone uses reflection or a delegate to call a method that was 'optimized' because it was only statically used in places where the object was ignored, but in the dynamic call case, they actually want the exception object?  The code's contract was again broken by the optimization, but from the other side this time.And that's not even addressing the real possibility (not that I've measured it) that a good portion of the performance issues with Exceptions involves unwinding the stack, which is something that would need to be done, even in the case where the exception object itself (and the expensive actions it entails, like building the stack trace) could be optimized away.