User: Password:
|
|
Subscribe / Log in / New account

Imaginary losses

Imaginary losses

Posted Mar 27, 2008 7:20 UTC (Thu) by alankila (guest, #47141)
In reply to: Imaginary losses by ncm
Parent article: Striking gold in binutils

I'm not sure what kind of code has been used to benchmark that, but assuming the C++ compiler
has to insert some low-level call such malloc() into the generated code to handle the new
operator (or whatever), it will have to detect the return code from malloc just the same as
the programmer using the C compiler.

In general, I suspect C code doesn't execute error paths a lot. In a malloc example there is
practically nothing to do but die if it fails. So you'd expect the C++ and C code to actually
perform pretty much the same instructions -- both would do the call, and both would test for
error, and in case of no error they move forward to the next user construct.

In case of error, the C program would do something the programmer wrote, the C++ would do
whatever magic is required to raise exception (hopefully without further memory allocations,
of course). After this point, things do diverge a lot, but I think in most cases there are no
errors to handle. 

Therefore, it would seem to me that both should perform identically, unless error returns are
a common, expected result, in which case you'd have to write dispatch logic in C to deal with
each error type (normally a O(log N) switch-case statement I'd guess) while the C++ compiler
would probably generate code to figure out which exception handler should receive the
exception.

Somehow I do get the feeling that C should win in this comparison. After all, it's testing the
bits of one integer, while C++ has to test exception class hierarchives. In light of this, it
seems ludicruous to claim that C error handlers cost a lot of code that need to be run all the
time, but somehow C++ exceptions are "free".


(Log in to post comments)

Imaginary losses

Posted Mar 27, 2008 7:56 UTC (Thu) by njs (guest, #40338) [Link]

malloc isn't the example to think of here, because yeah, usually you just abort. And the problem isn't that first if statement, where you detect the error in the first place. The problem is that in well-written C code, practically *every* function call has some sort of error checking wrapped around it, because errors in that function need to detected and propagated back on up the stack. It's the propagating that really hurts, because you have to do it with if statements, and if statements are expensive.

Compare C:

error_t foo() {
  char * blah;
  error_t e = bar(blah);
  if (!e)
    return e;
  e = baz();
  if (!e) {
    free(blah);
    return e;
  }
  /* ... */
}
versus C++:
void foo() {
  std::string blah = bar();
  baz();
  ...
}
One might think that the C++ code has "hidden" if statements; for old C++ compilers, that was true. Modern compilers, though, use Extreme Cleverness to avoid that sort of thing. (If you're curious for details, just g++ -S some simple programs and see.)

Imaginary losses

Posted Mar 27, 2008 20:40 UTC (Thu) by pphaneuf (subscriber, #23480) [Link]

You get a once per function (and thus, amortized better and better with the longer the function) setup and teardown that registers destructors. If there are no destructors, it simply can be left out. Even a "just crash" approach involves one test and branch per possible failure point.

On modern processors, having branches is expensive, due to mis-predicting them. I suspect that's one of the reasons that profile-driven optimizers can be so good, is that they can figure out which side of a branch is more likely. In the case of error-handling, which branch is more likely would be readily obvious to a human, but is harder to do for a compiler (see the annotations available in GCC, used by the Linux kernel code).

The code size increases with error-handling code, often with "dead spots" that get jumped over when there are no error, which on todays faster and faster machines, means increased instruction cache usage, less locality and so on.

I don't doubt that when they happen, C++ exceptions might be more expensive, but the thing with exception is that they don't happen often, and thus, that's the most interesting case.


Copyright © 2017, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds