Cost of throwing C++0x exceptions
#include <iostream>
#include <stdexcept>
struct SpaceWaster {
SpaceWaster(int l, SpaceWaster *p) : level(l), prev(p) {}
// we want the destructor to do something
~SpaceWaster() { prev = 0; }
bool checkLevel() { return level == 0; }
int level;
SpaceWaster *prev;
};
void thrower(SpaceWaster *current) {
if (current->checkLevel()) throw std::logic_error("some error message goes here\n");
SpaceWaster next(current->level - 1, current);
// typical exception-using code doesn't need error return values
thrower(&next);
return;
}
int returner(SpaceWaster *current) {
if (current->checkLevel()) return -1;
SpaceWaster next(current->level - 1, current);
// typical exception-free code requires that return values be handled
if (returner(&next) == -1) return -1;
return 0;
}
int main() {
const int repeats = 1001;
int returns = 0;
SpaceWaster first(1000, 0);
for (int i = 0; i < repeats; ++i) {
#ifdef THROW
try {
thrower(&first);
} catch (std::exception &e) {
++returns;
}
#else
returner(&first);
++returns;
#endif
}
#ifdef THROW
std::cout << returns << " exceptions\n";
#else
std::cout << returns << " returns\n";
#endif
}
Mickey Mouse benchmarking results:
$ make throw -B && time ./throw
g++ throw.cpp -o throw
1001 returns
real 0m0.547s
user 0m0.421s
sys 0m0.046s
$ make throw CPPFLAGS=-DTHROW -B && time ./throw
g++ -DTHROW throw.cpp -o throw
1001 exceptions
real 0m2.047s
user 0m1.905s
sys 0m0.030s
So in this case, throwing an exception up 1000 stack levels, rather than returning normally, takes about 1.5ms. That includes entering the try block, which I believe on some systems is free at execution time, on others incurs a cost each time you enter try, and on others only incurs a cost each time you enter the function which contains the try. For a more likely 100 stack levels, I upped the repeats to 10k because everything was 10 times faster. So the exception cost 0.1ms.
For 10 000 stack levels, it was 18.7s vs 4.1s, so about 14ms additional cost for the exception. So for this example we're looking at a pretty consistent overhead of 1.5us per level of stack (where each level is destructing one object).
Obviously C++0x doesn't specify performance for exceptions (or anything else, other than big-O complexity for algorithms and data structures). I don't think it changes exceptions in a way which will seriously impact many implementations, either positively or negatively.
Exception performance is very compiler dependent. You'll have to profile your application to see if it is a problem. In general, it should not be.
You really should use exceptions for "exceptional conditions", not general logic handling. Exceptions are ideal for separating normal paths through your code and error paths.
I basically think the wrong question has been asked.
What is the cost of exception is not usefull, more usefull is the cost of exceptions relative to the alternative. So you need to measure how much exceptions cost and compare that to returning error codes >>>AND<<< checking the error codes at each level of the stack unwind.
Also note using exceptions should not be done when you have control of everything. Within a class returning an error code is probably a better technique. Exceptions should be used to transfer control at runtime when you can not determine how (or in what context) your object will be utilised at runtime.
Basically it should be used to transfer control to higher level of context where an object with enough context will understand how to handlle the exceptional situation.
Given this usage princimple we see that exceptions will be used to transfer control up multiple levels in stack frame. Now consider the extra code you need to write to pass an error code back up the same call stack. Consider the extra complexity then added when error codes can come from multiple different directions and try and cordinate all the different types of error code.
Given this you can see how Exceptions can greatlly simplify the flow of the code, and you can see the enhirit complexity of the code flow. The question then becomes weather exceptions are more expensive than the complex error conditions tests that need to be performed at each stack frame.
The answer as always depends (do both profile and use the quickist if that is what you need).
But if speed is not the only cost.
Maintainability is a cost that can be measured. Using this metric of cost Exceptions alway win as they ultimately make the constrol flow of the code to just the task that needs to be done not the task and error control.
I once created an x86 emulation library and used exceptions for interrupts and such. Bad idea. Even when I was not throwing any exceptions, it was impacting my main loop a lot. Something like this was my main loop
try{
CheckInterrupts();
*(uint32_t*)&op_cache=ReadDword(cCS,eip);
(this->*Opcodes[op_cache[0]])();
//operate on the this class with the opcode functions in this class
eip=(uint16_t)eip+1;
}
//eventually, handle these and do CpuInts...
catch(CpuInt_excp err){
err.code&=0x00FF;
switch(err.code){
The overhead of containing that code in a try block made the exception functions the 2 of the top 5 users of CPU time.
That, to me is expensive