Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

During a code review with a Microsoft employee we came across a large section of code inside a try{} block. She and an IT representative suggested this can have effects on performance of the code. In fact, they suggested most of the code should be outside of try/catch blocks, and that only important sections should be checked. The Microsoft employee added and said an upcoming white paper warns against incorrect try/catch blocks.

I've looked around and found it can affect optimizations, but it seems to only apply when a variable is shared between scopes.

I'm not asking about maintainability of the code, or even handling the right exceptions (the code in question needs re-factoring, no doubt). I'm also not referring to using exceptions for flow control, this is clearly wrong in most cases. Those are important issues (some are more important), but not the focus here.

How do try/catch blocks affect performance when exceptions are not thrown?

like image 947
Kobi Avatar asked Aug 20 '09 19:08

Kobi


People also ask

Does try catch reduce performance?

try catch block does not slow down your program at all and is basically a standard for catching exceptions. Try Catch statements is basically your safe net when it comes to bugs in your code/program.

What happens if try catch block is not used?

3. If no exception occurs in try block then the catch blocks are completely ignored.

How does try catch affect performance?

In general, wrapping your Java code with try/catch blocks doesn't have a significant performance impact on your applications. Only when exceptions actually occur is there a negative performance impact, which is due to the lookup the JVM must perform to locate the proper handler for the exception.

Can we use try catch without throw?

Hi Shola, yes you can use try / catch without a throw. Nevertheless, as try / catch only makes sense if an exception can be thrown, this code would not make much sense.


2 Answers

Check it.

static public void Main(string[] args) {     Stopwatch w = new Stopwatch();     double d = 0;      w.Start();      for (int i = 0; i < 10000000; i++)     {         try         {             d = Math.Sin(1);         }         catch (Exception ex)         {             Console.WriteLine(ex.ToString());         }     }      w.Stop();     Console.WriteLine(w.Elapsed);     w.Reset();     w.Start();      for (int i = 0; i < 10000000; i++)     {         d = Math.Sin(1);     }      w.Stop();     Console.WriteLine(w.Elapsed); } 

Output:

00:00:00.4269033  // with try/catch 00:00:00.4260383  // without. 

In milliseconds:

449 416 

New code:

for (int j = 0; j < 10; j++) {     Stopwatch w = new Stopwatch();     double d = 0;     w.Start();      for (int i = 0; i < 10000000; i++)     {         try         {             d = Math.Sin(d);         }          catch (Exception ex)         {             Console.WriteLine(ex.ToString());         }          finally         {             d = Math.Sin(d);         }     }      w.Stop();     Console.Write("   try/catch/finally: ");     Console.WriteLine(w.ElapsedMilliseconds);     w.Reset();     d = 0;     w.Start();      for (int i = 0; i < 10000000; i++)     {         d = Math.Sin(d);         d = Math.Sin(d);     }      w.Stop();     Console.Write("No try/catch/finally: ");     Console.WriteLine(w.ElapsedMilliseconds);     Console.WriteLine(); } 

New results:

   try/catch/finally: 382 No try/catch/finally: 332     try/catch/finally: 375 No try/catch/finally: 332     try/catch/finally: 376 No try/catch/finally: 333     try/catch/finally: 375 No try/catch/finally: 330     try/catch/finally: 373 No try/catch/finally: 329     try/catch/finally: 373 No try/catch/finally: 330     try/catch/finally: 373 No try/catch/finally: 352     try/catch/finally: 374 No try/catch/finally: 331     try/catch/finally: 380 No try/catch/finally: 329     try/catch/finally: 374 No try/catch/finally: 334 
like image 86
Ben M Avatar answered Oct 20 '22 01:10

Ben M


After seeing all the stats for with try/catch and without try/catch, curiosity forced me to look behind to see what is generated for both the cases. Here is the code:

C#:

private static void TestWithoutTryCatch(){     Console.WriteLine("SIN(1) = {0} - No Try/Catch", Math.Sin(1));  } 

MSIL:

.method private hidebysig static void  TestWithoutTryCatch() cil managed {   // Code size       32 (0x20)   .maxstack  8   IL_0000:  nop   IL_0001:  ldstr      "SIN(1) = {0} - No Try/Catch"   IL_0006:  ldc.r8     1.   IL_000f:  call       float64 [mscorlib]System.Math::Sin(float64)   IL_0014:  box        [mscorlib]System.Double   IL_0019:  call       void [mscorlib]System.Console::WriteLine(string,                                                                 object)   IL_001e:  nop   IL_001f:  ret } // end of method Program::TestWithoutTryCatch 

C#:

private static void TestWithTryCatch(){     try{         Console.WriteLine("SIN(1) = {0}", Math.Sin(1));      }     catch (Exception ex){         Console.WriteLine(ex);     } } 

MSIL:

.method private hidebysig static void  TestWithTryCatch() cil managed {   // Code size       49 (0x31)   .maxstack  2   .locals init ([0] class [mscorlib]System.Exception ex)   IL_0000:  nop   .try   {     IL_0001:  nop     IL_0002:  ldstr      "SIN(1) = {0}"     IL_0007:  ldc.r8     1.     IL_0010:  call       float64 [mscorlib]System.Math::Sin(float64)     IL_0015:  box        [mscorlib]System.Double     IL_001a:  call       void [mscorlib]System.Console::WriteLine(string,                                                                   object)     IL_001f:  nop     IL_0020:  nop     IL_0021:  leave.s    IL_002f //JUMP IF NO EXCEPTION   }  // end .try   catch [mscorlib]System.Exception    {     IL_0023:  stloc.0     IL_0024:  nop     IL_0025:  ldloc.0     IL_0026:  call       void [mscorlib]System.Console::WriteLine(object)     IL_002b:  nop     IL_002c:  nop     IL_002d:  leave.s    IL_002f   }  // end handler   IL_002f:  nop   IL_0030:  ret } // end of method Program::TestWithTryCatch 

I'm not an expert in IL but we can see that an local exception object is created on fourth line .locals init ([0] class [mscorlib]System.Exception ex) after that things are pretty same as for method without try/catch till the line seventeen IL_0021: leave.s IL_002f. If an exception occurs the control jumps to line IL_0025: ldloc.0 otherwise we jump to label IL_002d: leave.s IL_002f and function returns.

I can safely assume that if no exceptions occur then it is the overhead of creating local variables to hold exception objects only and a jump instruction.

like image 45
TheVillageIdiot Avatar answered Oct 20 '22 01:10

TheVillageIdiot