views:

343

answers:

11

edit: Someone had added the C# keyword. I am NOT talking about C#, just exceptions in general. Specifically, exceptions in compiled languages like C++ and D; though C# was also in my mind.

I asked a question about exceptions and I am getting VERY annoyed at people saying throwing is slow. I asked in the past How exceptions work behind the scenes and I know in the normal code path there isn't any extra instructions (read the accepted answer) but I am not entirely convinced throwing is more expensive then checking return values. Consider the following

{
    int ret = func();
    if (ret == 1)
        return;
    if (ret == 2)
        return;
    doSomething();
}

vs

{
    try{
        func();
        doSomething();
    }
    catch (SpecificException1 e)
    {
    }
    catch (SpecificException2 e)
    {
    }
}

As far as I know there isn't a difference except the ifs are moved out of the normal code path into an exception path and an extra jump or two to get to the exception code path. An extra jump or two doesn't sound like much when it reduces a few ifs in your main and more often run) code path. So are exceptions actually slow? Or is this a myth or an old issue with old compilers?

A: 

it's like concating strings vs stringbuilder. it's only slow if you do it a billion times.

wefwfwefwe
i am asking the why. I am pretty sure it ISNT like concating strings
acidzombie24
because it has to unwind the stack, create the exception object, compare to the list of catchable exceptions etc. Obviously i'm comparing the effects of concating strings, not literally what happens
wefwfwefwe
btw i didnt -1 you. unwinding would happen when leaving the function via if(cond) return; compare the list sounds like many ifs of a switch. So i dont see the difference yet.
acidzombie24
don't worry i get -1d all the time ;) i get your point about the stack. i'd argue comparing exceptions is more heavyweight than comparing ints. But IMO it's unlikely to ever make a significannt difference in the real world.
wefwfwefwe
+2  A: 

In C# raising exceptions do have an every so slight performance hit, but this shouldn't scare you away from using them. If you have a reason, you should throw an exception. Most people who have problems with using them cite the reason being because they can disrupt the flow of a program.

Really if your reasons for not using them is a performance hit, your time can be better spent optimizing other parts of your code. I have never run into a situation where throwing an exception caused the program to behave so slowly that it had to be re-factored out (well the act of throwing the exception, not how the code treated it).

Thinking about it a little more, with all that being said, I do try and use methods which avoid throwing exceptions. If possible I'll use TryParse instead of Parse, or use KeyExists etc. If you are doing the same operation 100s of times over and throwing many exception small amounts of inefficiency can add up.

Kevin
A: 

Use exceptions and generally anything without worrying about performance. Then, when you are finished, measure the performance with profiling tools. If it's not acceptable, you can find the bottlenecks (which probably won't be the exception handling) and optimize.

Tamás Szelei
Someone went on a downvote-fury, or they haven't heard about premature optimization?
Tamás Szelei
Rewriting an application that uses return codes to use exceptions or visa-versa requires significant effort. It's really a decision that should be made in advance as it's so difficult to change later.
Joe Gauterin
That's genuinely a new perspective for me, thanks. I doubt that exceptions would be the bottlenecks in general though.
Tamás Szelei
+3  A: 

Here is an answer on Stackoverflow which shortly explains why.

Ikke
I don't see it as a very insightful explanation. In particular it doesn't address the assertion that there is signifincant cost in capturing the current stack information - in Java this certainly was the case.
djna
+5  A: 

I don't know exactly how slow it is, but throwing an exception that already exists (say it was created by the CLR) is not much slower, cause you've already incurred the hit of constructing the exception. ... I believe it's the construction of an exception that creates the majority of the addtional performance hit ... Think about it, it has to create a stack trace, (including reading debug symbols to add lines numbers and stuff) and potentially bundle up inner exceptions, etc.

actually throwing an exception only adds the additional code to traverse up the stack to find the appropriate catch clause (if one exists) or transfer control to the CLRs unhandled Exception handler... This portion could be expensive for a very deep stack, but if the catch block is just at the bottom of the same method you are throwing it in, for example, then it will be relatively cheap.

Charles Bretana
At least in C++ this is absolutely wrong. See my answer for an example - I'm throwing '0' -- that's about as cheap a construction as you can get. As far as reading debug symbols I would be really suprised if it did more than store the trace locations and deal with symbols lazily.
Aaron
@Aaron, I'm not a C++ expert by any means, but in yr code snippet, using the throw(1) statement, isn't it constructing an exception object? Even though you're only throwing(1), doesn't the compiler have to roll up that integer value into an Exception of some type? When you use the return value in the other case, are you not commenting put the throw(1) line? Just for grins, (I wonder what results will be?) - try constructing an exception without throwing it, return an op code to caller, and see how long that takes..
Charles Bretana
That would isolate the portion of the performance hit due to construction of the exception frpm the hit due to throwing it ...
Charles Bretana
Ok, from msdn. "3.If an exception is thrown during execution of the guarded section or in any routine the guarded section calls (either directly or indirectly), an exception object is created from the object created by the throw operand. (This implies that a copy constructor may be involved.) " Doesn't this meant that yr line reading throw(1) causes a constructor to be executed which instantiates an Exception Object?
Charles Bretana
+3  A: 

If you are using exceptions to actually control the flow it can be a pretty big hit.

I was digging in some old code to see why it ran so slow. In a big loop instead of checking for null and performing a different action it caught the null exception and performed the alternative action.

So don't use exceptions for things they where not designed to do because they are slower.

ElGringoGrande
A: 

If you want to know how exceptions work in Windows SEH, then I believe this article by Matt Pietrik is considered the definitive reference. It isn't light reading. If you want to extend this to how exceptions work in .NET, then you need to read this article by Chris Brumme, which is most definitely the definitive reference. It isn't light reading either.

The summary of Chris Brumme's article gives a detailed explanation as to why exception are significantly slower than using return codes. It's too long to reproduce here, and you've got a lot of reading to do before you can fully understand why.

Greg Beech
A: 

tl;dr IMHO, Avoiding exceptions for perf reasons hits both categories of premature and micro- optimizations. Don't do it.

Ah, the religious war of exceptions.

The various types of answers to this are usually:

  • the usual mantra (a good one, IMHO): "use exceptions for exceptional situations" (IOW, not part of "normal" code paths).
    • If your normal user paths involved intentionally using exceptions as a control-flow mechanism, that's a smell.
  • tons of detail, without really answering the original question
    • if you really want detail:
    • blogs.msdn.com/cbrumme/archive/2003/10/01/51524.aspx
    • blogs.msdn.com/ricom/archive/2006/09/14/754661.aspx
    • etc.
  • someone pointing at microbenchmarks showing that something like i/j with j == 0 is 10x slower catching div-by-zero than checking j == 0
  • pragmatic answer of how to approach performance for apps in general
    • usually along the lines of:
    • make perf goals for your scenarios (ideally working with customers)
    • build it so it's maintainable, readable, and robust
    • run it and check perf of goal scenarios
    • if a set of scenarios aren't making goal, USE A PROFILER to tell you where your time is being spent and go from there.
    • IOW, any perf changes, especially micro-optimizations like this, made without profiling data driving that decision, is typically a huge waste of time.

Keep in mind that your perf wins will typically come from algorithmic changes (adding an index to a table to avoid table scans, moving something with large n from O(n^3) to O(n ln n), etc.).

More fun links:

  • en.wikipedia.org/wiki/Program_optimization
  • www.flounder.com/optimization.htm
James Manning
+7  A: 

Okay - I just ran a little test to make sure that exceptions are actually slower. Summary: On my machine a call w/ return is 30 cycles per iteration. A throw w/ catch is 20370 cycles per iteration.

So to answer the question - yes - throwing exceptions is slow.

Here's the test code:

#include <stdio.h>
#include <intrin.h>

int Test1()
{
    throw 1;
//  return 1;
}


int main(int argc, char*argv[])
{
    int result = 0;
    __int64 time = 0xFFFFFFFF;
    for(int i=0; i<10000; i++)
    {
     __int64 start = __rdtsc();
     try
     {
      result += Test1();
     }
     catch(int x)
     {
      result += x;
     }
     __int64 end = __rdtsc();
     if(time > end - start)
      time = end - start;
    }

    printf("%d\n", result);
    printf("time: %I64d\n", time);
}

alternative try/catch written by op

try
{
        if(Test1()!=0)
    result++;
}
catch(int x)
{
        result++;
Aaron
Yes! finally someone with a real test and real answer.
acidzombie24
I wonder what its doing... But this at least tells me its a huge hit.
acidzombie24
Here is another in C#. Its also vastly slower. I wonder why expections are so different from return values. http://www.pastie.org/707883
acidzombie24
I've found that having the debugger attached to my C# programs can vastly change the results of benchmarking. I assume C programs can be subject to the same effect, so I hope you ran your benchmark with the debugger off.
Greg
@Greg - I did run it with the debugger off... Running under the debugger gets you 10,000 first chance exceptions you have to ignore.
Aaron
I ran it with the debugger off as well. I also notice the first exception and the second takes different amount of time (i assume its related to caching or in C# case the JIT) so i made sure the loop ran at least once before testing.
acidzombie24
+1  A: 

Yes. Exceptions make your program slower in C++. I created an 8086 CPU Emulator a while back. In the code I used exceptions for CPU Interrupts and Faults. I made a little test case of a big complex loop that ran for about 2 minutes doing emulated opcodes. When I ran this test through a profiler, my main loop was making a significant amount of calls to an "exception checker" function of gcc(actually there were two different functions related to this. My test code only threw one exception at the end however.) These exception functions were called in my main loop I believe every time(this is where I had the try{}catch{} part.). The exception functions cost me about 20% of my runtime speed.(the code spent 20% of it's time in there). And the exception functions were also the 3rd and 4th most called functions in the profiler...

So yes, using exceptions at all can be expensive, even without constant exception throwing.

Earlz
A: 

Part of the answer is that the compiler isn't trying very hard to optimize the exceptional code path.

  • A catch block is a very strong hint to the compiler to agressively optimize the non-exceptional code path at the expense of the exceptional code path. To reliably hint to a compiler which branch of an if statement is the exceptional one you need profile guided optimization.

  • The exception object must be stored somewhere, and because throwing an exception implies stack unwinding, it can't be on the stack. The compiler knows that exceptions are rare - so the optimizer isn't going to do anything that might slow down normal execution - like keeping registers or 'fast' memory of any kind available just in case it needs to put an exception in one. You may find you get a page fault. In contrast, return codes typically end up in a register (e.g. EAX).

Joe Gauterin