Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Try-Catch vs If performance in C# [duplicate]

I'm trying to both learn more about the implications of various design choices, and find the most performant solution for preventing errors in my code. Before diving in, allow me to briefly and generally state my question:

Is a try catch block a more efficient solution to handling an out of bounds exception when compared to and if-statement structure?

I understand that raising exceptions is expensive, but is that cost mitigated by removing unnecessary if-statements?

And now, allow me to state my specific issue to give you more useful information.

I'm building a game, and part of that game is a world-grid solution coupled with a pathfinder. Game Units may request nodes from the world-grid, (by sending coordinate information as an ordered pair (x, z)), to then send to the pathfinder or perform on them some other miscellaneous action. Because nodes are being requested with a large amount of frequency, especially by the pathfinder, this seems like a smart place to try to optimize.

Here is my current code for returning a given node based on its x and z values in the array of nodes:

public Node GetTile(int x, int z)
{
    if (x < 0)
        x = 0;
    if (x >= length_X)
        x = length_X - 1;

    if (z < 0)
        z = 0;
    if (z >= length_Z)
        z = length_Z - 1;
    return tiles [x, z];
}

As you can plainly see, I have several if statements in place to avoid out of bounds exceptions when retrieving a node from world-grid's array of nodes(tiles). Is this the most efficient solution? Could I remove the if's and instead place the return in a try catch block like so:

public Node GetTile(int x, int z) 
{
    try
    {
        return tiles[x, z];
    }
    catch (System.IndexOutOfRangeException e)
    {
        //handle exception here
        //do smart programming fix-y stuff
    }
}

This solution works, but is there some reason that I'm not aware of that makes it less efficient? My logic for believing it to be a smarter solution is that I'm removing up to four comparisons every single time the method is called. Considering the circumstances under which the program will actually send in values out side of the bounds are rare, this seems like a good trade off. What I don't know though, is how exceptions work behind the scenes. Will checking for an exception be just as expensive as checking the values manually?

UPDATE:

After reading through the replies here I now have a better understanding of the topic in general. I've run some tests on my code accounting for various cases running 10 million iterations.

In line with my general hypothesis, if we assume that there will never be a case where input results in an exception, then the try catch block is indeed faster. However, in the case where approximately 10% the calls to the method raise an exception, the performance is over 5 times slower. I tested various percentages and it seems that the threshold for better performance in my case is near 1%.

As of yet, I'm not sure what percentage of calls will indeed actually raise an exception, but I believe that the number will be much much lower than 1%. Therefore, I can safely, unless further testing shows otherwise, use the try-catch block to ensure my code runs without fatal errors.

Thanks to everyone who contributed.

like image 412
Caboose Avatar asked Sep 26 '16 19:09

Caboose


People also ask

Is try catch faster than if?

If you've one if/else block instead of one try/catch block, and if an exceptions throws in the try/catch block, then the if/else block is faster (if/else block: around 0.0012 milliseconds, try/catch block: around 0.6664 milliseconds). If no exception is thrown with a try/catch block, then a try/catch block is faster.

Is try catch better than if-else?

'try-catch' is more time consuming than 'if-else'. 'if-else' communicate between the data provided to the program and the condition. 'try-catch' communicate between the data with the conditions and the system.

Does try catch reduce 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.

Are try catch statements Slow?

try catch block does not slow down your program at all and is basically a standard for catching exceptions.


1 Answers

Exceptions are not made to control the flow of your code. They are made to treat "exceptional" circumstances, e.g. connection issues or invalid file formats.

If you want to control your code flow, you should use conditional statements like if, else and switch.

The performance of exceptions is generally bad compared to some simple if-statement, but there are also situations when exception-handling might be even faster than checking data for validity manually, especially if you don't know how to do it fast. There might also be plenty of situations where you "know" an exception could be raised, but you simply trust the data - e.g. checking your own settings file for valid xml format.

Most of the time, you want to use Exceptions, to have error information later, e.g. line number of the error in the xml file and to recover your application in some way (e.g. reconnect to a socket).

You can not give a general statement about the performance of exceptions, but when you can avoid them, you should. They are made for exceptions as their name already tells.

A small example where you can potentially avoid exceptions:

try
{
    LoginUser("Fooooo", "Bar");
} catch(InvalidPasswordException e) {
    MessageBox.Show(e.Message);
}  

private static void LoginUser(string pUsername, string pPassword)
{
    if (pUsername != "Foo" || pPassword != "Bar")
       throw new InvalidPasswordException("Invalid username and/or password");
    
    GrantAccess(pUsername);
}

Instead of throwing the exception you could also just return a boolean:

if (!LoginUser("Fooooo", "Bar"))
{
    MessageBox.Show("Invalid username and/or password");
}

private static bool LoginUser(string pUsername, string pPassword)
{
    if (pUsername != "Foo" || pPassword != "Bar")
        return false;
        
    GrantAccess(pUsername);            
    return true;
} 

Performance-Test: 10000 attempts with false credentials:

throwing Exception (without displaying the messagebox): 181990454 ticks

returning boolean: 644 ticks

And we are only 1 layer into the application, so there is not much stacktrace to be generated. I guess you can see and especially feel the difference.

like image 105
Dominik Avatar answered Oct 06 '22 19:10

Dominik