Re: How do you exception in your daily C++ programming? - test.cpp (0/1)
on Sat Sep 05 2009, George Neuner <gneuner2-AT-comcast.net> wrote:
On Fri, 4 Sep 2009 17:31:34 CST, David Abrahams <dave@boostpro.com>
wrote:
on Fri Sep 04 2009, George Neuner <gneuner2-AT-comcast.net> wrote:
and possibly deadly for real time code.
Well now, that's true. Possibly deadly. Test and measure to find out.
The whole discussion is meaningless unless you're considering high
performance code ... at minimum soft real time.
HPC and soft real time are almost the same as far as this is concerned:
you can tolerate something being arbitrarily slow (within reason) as
long as you do it extremely rarely. In other words, you can probably
afford to use EH, providing you're not throwing in your inner loop. It
certainly won't be "deadly."
We are only talking about, at most, milliseconds ... but that might
matter to a real time program on a slower processor - not every
program will be run on 3GHz 64-bit quad-cores.
Now you're talking about hard real time, as I understand it. Yes, any
operation you might perform could be deadly to such a system if it takes
long enough, no matter how rare it is. You have to test and measure
/everything/ (not just EH).
But regardless, catching close to the throw point doesn't help you at
all if you don't throw. Otherwise, you pay about a 25x penalty per
stack frame (on my g++ implementation) to unwind. If you can't afford a
25x slowdown on the EH paths in the rare instance an exception does
occur, you've got a problem with EH.
Compiled for maximum speed, on my 3Ghz dual Pentium 4 Windows box, the
difference between the timing of the normal return path and the
exception return path for a 2 level nested call is 80..200x depending
on whether there are local dtor objects (the no objects case is
actually worse as there more hidden exception overhead).
Unless you're targeting 64-bit windows, you're not testing a
particularly good EH implementation.
??? 64-bit Windows uses the same SEH implementation as 32-bit.
Did I mention SEH? This is a C++ Newsgroup.
But, unless I'm mistaken, MS used the Itanium ABI's[1] general C++ EH
mechanism for SEH on Win64 as well as in their C++ compiler.
C++ EH is slightly faster than Windows SEH. In VS2008 you can choose
which to use. If you mean the 64-bit compiler has a better C++ EH
implementation, then I have to plead ignorance ... I'll have to look
into it.
I am talking about C++ EH.
I don't have a Unix or Linux box handy to test GCC natively. I get
roughly similar timings using GCC in cygwin. GCC is slightly better
with no local objects and VS2008 is slightly better with local
objects.
Like MS's Win32, Cygwin also uses a poor EH implementation based on
setjmp/longjmp.
VS2008 uses a table based implementation unless you select SEH
handling.
That's a recent development, then. In any case, I don't know anything
about the quality of that implementation. I can run my tests here on a
VM when I get some more time.
Cygwin is an older version of G++ (3.4.5) so that - I don't
have a 4.4 to test so that will definitely make a difference.
IIRC it's not a matter of which version of G++ you have; it's a question
of whether they've integrated table-based EH into the runtime for the
Cygwin platform. Last I checked, nobody had bothered to do that port,
so Cygwin still used setjmp/longjmp even with the latest compilers.
The recommended implementation of exceptions certainly does not
provide a cheap throw. On the other hand, if no exceptions happen,
there is no overhead.
This isn't true. Even with the table address-range implementation,
there is additional work done by the preamble of any function that
contains a try block.
I don't think so. What additional work do you think needs to be done in
that case? And, what's a preamble ;-)?
The preamble is the code that sets up the call frame.
Table based EH implementations need no runtime setup to catch
synchronous C++ exceptions,
Right.
but if you use OS structured exceptions (in Windows or Linux)
I've never heard of such a thing existing on Linux, although I suppose
you could view the generalized Itanium ABI EH mechanism that way since
it works across languages...
then there is extra EH information placed in the stack frame.
....but that's table-based, so it doesn't need any extra info in the
stack frame.
the compiler has no way of knowing that it doesn't need to keep the
value of a around for use in the catch block. This effect usually takes
the form of what's known as "register pressure." As far as I can tell,
register pressure can only happen with try/catch, though, and not object
destructors, since destructors have to run whether or not an exception
is thrown.
Mostly it translates as memory traffic because register values have to
be flushed to memory ahead of the try block so they can be restored
later if necessary.
No, a throw() is just like any other function call; register values get
pushed onto the stack in the usual ways and places; a table-based EH
implementation knows where to find them. Register pressure means that
you don't get to re-use a register for other purposes in the
straight-line code because you can't tell that the catch block is
unreachable.
Footnotes:
[1] http://www.codesourcery.com/public/cxx-abi/abi.html,
http://download.intel.com/design/Itanium/Downloads/245370.pdf, etc.
--
Dave Abrahams
BoostPro Computing
http://www.boostpro.com
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]