This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

The price of Exceptions with COFF ABI

Does anyone know of a set of figures that quantify the overhead (maybe in terms of additional instructions, or of code-size growth), or some other explanation as to how enabling c++ Exceptions affects an application compiled for COFF ABI?  There are a couple of SPRUs around that mention a significant overhead, but I haven't seen one that goes into much detail.  I'm curious what that looks like--Not necessarily looking for a thesis, but maybe just a general idea of what to expect.

Thank you!
_matt 

  • I'm not aware of any specific numbers to quantify the overhead of exceptions.  To me, the important point is that you pay that overhead whether or not any exceptions are ever thrown.

    A side note just for those who use EABI ... For you, there is no cycle count overhead, provided no exceptions are thrown.  But there is additional cost in terms of memory.

    For details on all of this, please see this wiki article.

    Thanks and regards,

    -George

  • The overhead of the COFF ABI implementation of exception handling is roughly proportional to the number of "try" blocks executed (we do not consider the cost of catch blocks, as these should only be reached in exceptional cases), and so it will vary greatly depending on the nature of your program.    If your program has only one "try" block in main, it is unlikely to impact performance much.  If your program makes heavy use of templates and the "new" operator, the overhead is going to be much larger.

    The COFF ABI essentially uses "setjmp", so when you write a "try" block, you are incurring not only the cost of a function call, but also the lost optimization opportunities because the compiler must be conservative when generating code around the call.  In effect, the price of one try block is one call to setjmp, plus the fact that code in the try block and any blocks that contain the try block are not well-optimized.

  • Thanks for the explanation, but just to clarify:   Is there a penalty for a call to a method that potentially throws an exception, even though it is not within a try block?

    By way of example: if DoSubTask() potentially threw an exception, is there a context-save somewhere within DoTheTask()?

     

    void DoTheTask() {

     while(!done) {

       result = DoSubTask();

       // Crunch result, or something

     }

    }

    main() {

      try {

        DoTheTask();

     }

    ...

    }

     

    Thanks,

    _matt

  • There is no extra cost for a function, regardless of whether it can propagate exceptions or not.   The call to setjmp to implement the try/catch statement is what saves the context.  There is a cost for creating a local object that needs to be destructed if an exception occurs during its lifetime.  Every local non-POD object (POD is "plain old data", non-POD means a class, struct, or union with methods) must register itself at run time so that it can be destructed if an exception occurs during its lifetime.  So, if you don't use any non-POD objects, you won't incur any extra expense over the expense associated with calling setjmp to set up the try/catch statement.