How slow are exceptions?

Started by
40 comments, last by legalize 16 years, 5 months ago
Quote:Over generalize much?


I missed that original quote included exception propagation as well.

Originally I referred to impact of exceptions-based code vs. the cost of what happens once the exception is thrown - which will inevitably be costly.
Advertisement
Quote:Original post by Numsgil
Since exceptions should be relatively rare, and only occur when something EXCEPTIONal happens, something that wasn't expected. Performance should be the least of your worries in these cases.

Well, an exception is something which is not the norm. It doesn't have to be exceptionnal - that's rather limiting.

Quote:Original post by Antheus
I missed that original quote included exception propagation as well.

And you'd still be overgeneralizing because a) many languages have cheap exception object construction and b) it's possible to have an exception handler implementation where exceptions are quite fast by decreasing the performance of code in the general case such as SJLJ implementations.
Anybody knows a good link describing in details how C++ exceptions are implemented for the most common compiler/platform.
Well, I'm not sure about the implementation in detail, however I know the newest versions on MinGW actually come in two versions with different mechanisms:

1) SJLJ (as SiCrane said): uses C library functions setjmp/longjmp for control flow (involves calling setjmp whenever you enter a try block; might also involve calling setjmp whenever you construct a non-POD object stack because that would require the destructor to be called if an exception is thrown).

2) DWARF2: no performance penatly in regular code flow, uses debugging information (hence DWARF2) to figure out how to throw exceptions.

That's about all I know about mechanisms; Microsoft has its own mechanism (SEH - Structured Exception Handling, I have no idea how that works technically), but my point is I don't think there is one 'most common' mechanism.
Quote:Use exceptions until you've profiled your application and determined that exceptions cost too much.

Bwahahaa! There's nothing like failing to look before you leap; the end result may be something you'd like to change, but simply can't because there's way too much that depends on it.
Time for some due diligence beforehand: (http://www.on-time.com/ddj0011.htm; the numbers are somewhat dated, but quite interesting)

Program			Code Size	Time (no throws)	Time (with throws)XBench.c		4.6k		1392 ms				1362 msCPPBench.cpp	35.3k		1492 ms				71343 ms


That's the kind of difference I'd like to know beforehand, while it's not yet too late.

Quote:Since exceptions should be relatively rare, and only occur when something EXCEPTIONal happens, something that wasn't expected. Performance should be the least of your worries in these cases.

Would that it were this simple, but both of the common ways of implementing C++ exceptions have serious overhead (prolog/epilog, or large tables) regardless of whether the exceptions actually fly or not.
Let's have a look at the way things work under the hood:
http://www.microsoft.com/msj/0197/exception/exception.aspx
http://blogs.msdn.com/cbrumme/archive/2003/10/01/51524.aspx
http://www.codeproject.com/cpp/exceptionhandler.asp

And then read this interesting anecdote/opinion piece:
http://www.seventhstring.com/resources/exceptionfree.html

Personally, I like RAII and find automatic cleanup without bailout ladders convenient. Even toss in a few exceptions when things happen where the only thing you can do is a controlled crash&burn (machine-check exception, out of memory*). But: EOFException et al. really are the kind of goto-travesty people are so happy to jump on, yet even worse, because they may end up jumping ANYWHERE. (heh, that's not going to bode well for static analysis..)


* this probably needs expanding upon. You might ask: why not just roll back the current transaction or whatever if there's not enough memory to do it? That may work from the perspective of a single routine, but I bet not all code will have been tested for this and your app WILL die. Also, the fact that memory is exhausted probably indicates a bug somewhere else (leak, overflow/incorrect calculation). Some go further and say: there should be no runtime allocations at all, but that may be a bit too extreme for most projects.
E8 17 00 42 CE DC D2 DC E4 EA C4 40 CA DA C2 D8 CC 40 CA D0 E8 40E0 CA CA 96 5B B0 16 50 D7 D4 02 B2 02 86 E2 CD 21 58 48 79 F2 C3
Quote:Original post by Jan Wassenberg
Quote:Use exceptions until you've profiled your application and determined that exceptions cost too much.

Bwahahaa! There's nothing like failing to look before you leap; the end result may be something you'd like to change, but simply can't because there's way too much that depends on it.
Time for some due diligence beforehand: (http://www.on-time.com/ddj0011.htm; the numbers are somewhat dated, but quite interesting)

Program			Code Size	Time (no throws)	Time (with throws)XBench.c		4.6k		1392 ms				1362 msCPPBench.cpp	35.3k		1492 ms				71343 ms



Umm, you do realize that those time differences are showing how long it takes to throw 0 exceptions, vs throwing and catching 1,000,000 exceptions?

Look at the code...
--Michael Fawcett
Quote:Umm, you do realize that those time differences are showing how long it takes to throw 0 exceptions, vs throwing and catching 1,000,000 exceptions?

No, I do not. Look at example 2 to see that XBench.c throws and catches "exceptions" much like CPPBench.cpp; the difference is that it uses a home-brewed method akin to SEH.
Or maybe you have chosen a narrow definition of "exception"; if that's the case, let's not bandy semantics.
E8 17 00 42 CE DC D2 DC E4 EA C4 40 CA DA C2 D8 CC 40 CA D0 E8 40E0 CA CA 96 5B B0 16 50 D7 D4 02 B2 02 86 E2 CD 21 58 48 79 F2 C3
Quote:Original post by bulgurmayo
Anybody knows a good link describing in details how C++ exceptions are implemented for the most common compiler/platform.
Just this week I watched a Microsoft video at work, about how exception handling was implemented. On WIN32 functions with exception information are added-to / removed-from a linked list upon entry and exit. This means that simply using exception handling adds a certain overhead, but throwing is not as costly as it might otherwise be.
On x64 each function has a table containing the object lifecycle information and is indexed by the instruction pointer. Simply using exceptions is very cheap, but throwing them is considerably more expensive.
.NET is different again, but they didn't go into the details.
Sorry I don't have a link to it.
"In order to understand recursion, you must first understand recursion."
My website dedicated to sorting algorithms
Quote:Original post by iMalc
Just this week I watched a Microsoft video at work, about how exception handling was implemented. On WIN32 functions with exception information are added-to / removed-from a linked list upon entry and exit.


What exactly is meant by "functions with exception information"?

Functions that throw?

Functions that catch?

Functions that have an exception signature?

*Every* function?

Do you have a link to the video? (Was it on Channel 9?)

My free book on Direct3D: "The Direct3D Graphics Pipeline"
My blog on programming, vintage computing, music, politics, etc.: Legalize Adulthood!

This topic is closed to new replies.

Advertisement