(Print this page)

Try-catch structure overhead in .Net
Published date: Monday, March 21, 2016
On: Moer and Éric Moreau's web site

I have heard something funny lately for which I was very skeptical but had no arguments. That funny thing was that the guy was not using the try-catch structure saying it was a performance killer. Of course I was sure that setting up the exception handling had a cost but was not sure of how much cost.

I decided to measure the overhead so if I ever met that guy again, I will be equipped with real facts!

The downloadable demo

Once again, the solution is provided with both a VB and a C# project. It was created using Visual Studio 2015 but the same thing would also be exactly the same in previous versions.

Figure 1: The demo application in action

The whole point

The whole point of this month article is to demonstrate how much overhead is the try-catch structure is impacting your application.

To try to demonstrate this, let’s start by creating 2 methods that we will call in a loop and check the time required.

These are my 2 methods:

Private Sub EmptyMethod()
End Sub
 
Private Sub TryCatchMethod()
    Try
    Catch ex As Exception
    End Try
End Sub

Nothing fancy here. The first method (EmptyMethod) is completely empty. It will just be called in a loop to set the base for the cost of a method call.

The second method (TryCatchMethod) is mostly empty except for an empty try catch structure. The purpose of this method, also called in a loop with the same number of iterations will help us determine the amount of overhead used by this structure when no exception is raised by the code.

With these 2 methods in place, we can now start doing performance test.

Comparison of the results

The important thing to remember is not the exact time taken as your result may and will vary on your own computer. The important thing to remember is the order of magnitude.

To provide results, I created a small Windows Forms application that you can download. The application let you enter the number of iterations (number of time the 2 methods will be called). Here is the interesting code:

'Test the empty method
ShowResult("Testing EmptyMethod...", True)
sw.Reset()
sw.Start()
For i As Integer = 1 To iterations
    EmptyMethod()
Next
ShowResult($"EmptyMethod = {sw.ElapsedMilliseconds} ms", False)

'Test the method containing an empty try catch structure
ShowResult("Testing TryCatchMethod...", True)
sw.Reset()
sw.Start()
For i As Integer = 1 To iterations
    TryCatchMethod()
Next
ShowResult($"TryCatchMethod = {sw.ElapsedMilliseconds} ms", False)

When you will run it, you will find out that if you don’t have enough iterations, you just don’t get significant results. On my machine, that number is 1 million. At that level, the 1 million calls to the empty method takes around 5 ms (often less) while 1 million calls to the method having the empty try-catch structure run in about 15 ms. So the hit is about 3 times.

But I don’t know about you, but I don’t remember the last time I had to run a loop calling a method at least 1 million time.

And the factor seems to have a linear progression. Do the test for 1 billion iterations (1,000,000,000) and you will still observe that factor of 3 (one of my test is reporting 5408 ms for the first method and 15283 ms for the second one). So yes in that case it is a difference of 10 seconds but we just looped 1 billion time.

What if an exception is thrown?

This is when you will be hurt.

I have created another method essentially empty except that it throws an exception:

Private Sub ThrowMethod(pException As Exception)
    Try
        Throw pException
    Catch ex As Exception
    End Try
End Sub

For comparison purposes, I run this method in a loop just like I did for the 2 other methods but this time I limit the number of iterations to 100 just because I have never been patient enough to wait for the full loop to complete with previous iterations:

'Test the method that throws an exception
'Limiting the number of iterations for this one
If iterations > 100 Then iterations = 100
Dim ex = New Exception()
ShowResult($"Testing ThrowMethod for {iterations} iterations...", True)
sw.Reset()
sw.Start()
For i As Integer = 1 To iterations
    ThrowMethod(ex)
Next
ShowResult($"ThrowMethod = {sw.ElapsedMilliseconds} ms", False)

My test shows that 100 iterations here takes about 2 seconds. This is even longer than 100,000,000 iterations as you can see in figure 1. And if you look at my code, we are not even declaring and instantiating a new exception, that was already done! Throwing a new exception 100 times would take about 3 seconds on my computer!

So the real culprit is not the try-catch structure, it is really the throw exception mechanism.

I know some people who instead of return error code are throwing exceptions. I hope that those people will now revisit their code!

Could have we done the test differently?

The answer of course is yes. We could have surrounded the For-loop in a try-catch structure so we have the overhead of only one structure but this is not what I wanted to check.

I really wanted to see the impact of that structure alone and I really think that this demo really shows that there is an impact but I wouldn’t personally remove all my try-catch from my applications.

I have seen other people adding the try-catch structure literally in every method. Would I personally do it? No but I wouldn’t tell somebody to remove them all for performance reason (unless the code is running in a loop for a huge number of iterations!).

Conclusion

I can’t wait to see the guy who was saying that the try-catch structure alone was killing its performance. I am not saying it has no impact but the impact of that structure alone is negligible considering the benefits it gives you building robust applications.


(Print this page)