Try-Catch Speeding Up My Code

Try-catch speeding up my code?

One of the Roslyn engineers who specializes in understanding optimization of stack usage took a look at this and reports to me that there seems to be a problem in the interaction between the way the C# compiler generates local variable stores and the way the JIT compiler does register scheduling in the corresponding x86 code. The result is suboptimal code generation on the loads and stores of the locals.

For some reason unclear to all of us, the problematic code generation path is avoided when the JITter knows that the block is in a try-protected region.

This is pretty weird. We'll follow up with the JITter team and see whether we can get a bug entered so that they can fix this.

Also, we are working on improvements for Roslyn to the C# and VB compilers' algorithms for determining when locals can be made "ephemeral" -- that is, just pushed and popped on the stack, rather than allocated a specific location on the stack for the duration of the activation. We believe that the JITter will be able to do a better job of register allocation and whatnot if we give it better hints about when locals can be made "dead" earlier.

Thanks for bringing this to our attention, and apologies for the odd behaviour.

try catch for performance c#

The link I provided in the above comment shows a description of why you shouldn't ever use a try-catch when an if-statement would prevent the exception from being thrown, but in the interest of showing performance in terms of actual numbers, I wrote this quick little test program.

Stopwatch watch = new Stopwatch();

int[] testArray = new int[] { 1, 2, 3, 4, 5 };
int? test = null;

watch.Start();
for (int i = 0; i < 10000; i++)
{
try
{
testArray[(int)test] = 0;
}
catch { }
}
watch.Stop();

Console.WriteLine("try-catch result:");
Console.WriteLine(watch.Elapsed);
Console.WriteLine();

watch.Restart();
for (int i = 0; i < 10000; i++)
{
if (test != null)
testArray[(int)test] = 0;
}
watch.Stop();

Console.WriteLine("if-statement result:");
Console.WriteLine(watch.Elapsed);

The result of the program is this:

try-catch result:
00:00:32.6764911

if-statement result:
00:00:00.0001047

As you can see, the try-catch approach introduces significant overhead when an exception gets caught, taking over 30 seconds to complete 10,000 cycles on my machine. The if-statement, on the other hand, runs so fast that it is basically instantaneous. Compared to the try-catch, this is a performance improvement in the neighborhood of 3,000,000%.

(This isn't a rigorous benchmark, and there are ways to write it and run it differently to get more precise numbers, but this should give you a good idea of just how much more efficient it is to use an if-statement over a try-catch whenever possible.)

How to create a generic try catch repeated code?

You can create a method which accepts Func as parameter:

class Request{} 
class BadRequest:Request{}
class AnotherRequest:Request{}

static Request HandleException(Func<Request> f)
{
Request result ;
try
{
result = f();
}
catch (Exception ex)
{
result = new BadRequest();
}
return result;
}

static AnotherRequest SomeMethod(int i) => new AnotherRequest();

And usage:

Request result = HandleException(() => SomeMethod(1));

Try/catch is not getting the inner exception thrown by Assert in c#

You will need to specifically catch TargetInvocationException, and access the .InnerException as the cause, i.e.

try
{
callingUnitTestMethod();
return new TestResult {Name = "TestName", Status = "Success", Error = "NA"};
}
catch (TargetInvocationException tex)
{
return new TestResult {Name = "TestName", Status = "Fail",
Error = tex.InnerException.Message};
}
catch (Exception ex)
{
return new TestResult {Name = "TestName", Status = "Fail", Error = ex.Message};
}

Remove Try/Catch statements from asp.net controllers

Absolutely agree, anything that has try/catch implemented everywhere is a code smell and there's a better way of doing things.

If you search for 'Global Exception Handling netcore' you'll find a lot of hits on this subject.

In general, let the exception propagate up the stack, preserve all the exception detail and let it be caught and handled by a Middleware. Probably a bit too much code to snippet into this answer, but here's decent article with a couple of different versions/examples available

https://jasonwatmore.com/post/2022/01/17/net-6-global-error-handler-tutorial-with-example

You'll notice returning responses from the middleware, and this is your opportunity to perform logging centrally as well - a single place to capture and log all your exception details.

Returning a bool value inside Try-Catch block in C#

This is because neither FirstOrDefault() or Remove() will throw an exception when not finding a value in your list.

You could either return false if you didn't find your item (prod == null).

Or just return the result of Remove() (though if you have a null item and did not find an item with the provided id, you'd end up removing it and returning true either way)

As it is right now, the only case where your method would return false is when your list is null, resulting in a NullReferenceException

Does try-catch block decrease performance

TL;DR NO, exceptions are usually faster on the non-exceptional path compared to error code handling.


Well, the obvious remark is compared to what ?

Compared to not handling the error, it obviously decrease performance; but is performance worth the lack of correctness ? I would argue it is not, so let us supposed that you meant compared to an error code checked with an if statement.

In this case, it depends. There are multiple mechanisms used to implement exceptions. Actually, they can be implemented with a mechanism so close to an if statement that they end up having the same cost (or slightly higher).

In C++ though, all major compilers (gcc introduced it in 4.x serie, MSVC uses it for 64 bits code) now use the Zero-Cost Exception Model. If you read this technical paper that Need4Sleep linked to, it is listed as the table-driven approach. The idea is that for each point of the program that may throw you register in a side-table some bits and pieces that will allow you to find the right catch clause. Honestly, it is a tad more complicated implementation-wise than the older strategies, however the Zero Cost name is derived by the fact that it is free should no exception be thrown. Contrast this to a branch misprediction on a CPU. On the other hand, when an exception is thrown, then the penalty is huge because the table is stored in a cold zone (so likely requires a round-trip to RAM or worse)... but exceptions are exceptional, right ?

To sum up, with modern C++ compilers exceptions are faster than error codes, at the cost of larger binaries (due to the static tables).


For the sake of exhaustiveness, there is a 3rd alternative: abortion. Instead of propagating an error via either status or exception, it is possible to abort the process instead. This is only suitable in a restricted number of situations, however it optimizes better than either alternative.

try-catch instead of if in edge cases

I would agree with PMF: Depends!

On your specific use case and in specific whether something is your fault or something you can't control / predict.

So in general I'd say there are three ways of how to handle stuff that isn't behaving as expected

  • A) let throw an exception to indicate that this is really bad and there is no way to recover => and most probably crash your app

    This usually makes totally sense on development time because while debugging you explicitly want your app to crash so you can find and fix the issue.

    This should be happening for everything where the cause is basically something that you messed up and can be fixed by you. (In your case instance not initialized correctly)

  • B) return something e.g. false to indicate that something went bad but allow this to be handled by the code and e.g. try something else.

    In my eyes this should be the preferred way of dealing with stuff you can't control yourself like e.g. user input and other unpredictable conditions like internet connectivity etc.

  • C) Just ignore it and do nothing at all.

    Depends of course on what exactly you are doing but this should actually happen almost never. For a User this can be extremely frustrating and also for you as developer it makes debugging hard to impossible!

    In combination with B of course this is valid since something else will already have delt with the issue.

And to add just in general unless you work on some core / reused library I would actually never throw exceptions myself except you are re-throwing caught ones to add additional debugging information. This basically falls under "you can't control" how others will use your library -> this basically from your perspective falls under user input ;)


Now all three options can be achieved by try - catch or if checks internally of course and it depends on your specific case which way you want to go.

Some thoughts of mine on this

  • Readability wise I would prefer the if already alone because it makes clear exactly which condition is checked. When I see a try - catch I don't know exactly at which point which exact exception might be thrown on first glance.

    Thus using try - catch as a replacement for if just obscures what exactly is failing and makes debugging hard to impossible

  • Exceptions are quite expensive! So performance wise I would say use if wherever possible.

  • There are cases though - and in my opinion these are the only ones where try - catch would be allowed - where you use a library and there simply is no way to prevent an exception.


Example: FileIO

  • the file you want to access does not exist

    -> You don't need try - catch for this (in my eyes it would be the lazy way). This is something you can and should actually check first if(!File.Exists(...)) so your program can correctly deal with it and handle that case (e.g. you might want to tell the user instead of simply crash or doing nothing).

  • The file is currently opened by another program so you can't write to it.

    -> There is no way to find this out beforehand. You will get an exception and can't avoid it. Here you want to try - catch in order to still allow your code to deal with such case (as before e.g. tell the user instead of simply crash).

But then how you actually deal with them again depends:

  • If you e.g. use some hardcoded paths and these files definitely should be there -> Exception because it means you as developer messed something up.

  • If the path comes from user input -> Catch because this is something you as developer can't control but don't just want your app to crash, rather show a hint to the user that he messed it up.


Now in your use case the Example 1 both of your solutions seem pretty bad to me. You go with the last option C and just ignore the call - a user won't see the warning and also a developer might just not note / ignore it.

You definitely want to get an Exception here if this means that your app will not behave correctly and not catch it at all!

In general there is no need for a special bool flag. I would rather go with

if(instance == null)
{
Debug.LogError(...);
return;
}

Because this is most probably a more severe error not only a warning so it at least gains visibility.

In your Example 2 you actually have kind of a lazy initialization anyway so either way the call itself is basically valid.

In such case though again this is something you can easily check and I would not wait for an exception (especially not simply any) because I already know that there definitely will be one at least once.

In my opinion this should rather be

if(instance == null)
{
// I have put `???` because, well, in a "static" method there is no "this" so
// I wonder where the instance should come from in that case ;)
instance = ???;
}

instance.alj = v;


Related Topics



Leave a reply



Submit