News for hackers. Stuff that matters.
Re:Investigating the Performance Overhead of C++ Exceptions by thedance on Tuesday February 11, 2020 @03:53PM (#22302719)
It should be well-known that actually throwing an exception in C++ is extremely costly. I think it is also fairly widespread knowledge that even allowing the compiler to support exceptions has runtime costs. Exceptions do not conform to C++'s "zero-overhead" principle. That's why numerous large organizations from NASA to the Dept. of Defense to Google decree that C++ exceptions must not be used.
Re:Investigating the Performance Overhead of C++ Exceptions by gumby on Tuesday February 11, 2020 @07:59PM (#22304701)
> Exceptions do not conform to C++'s "zero-overhead" principle. That's why numerous large organizations from NASA to the Dept. of Defense to Google decree that C++ exceptions must not be used.

I don't know about NASA's case, but Google's style guide forbids exceptions only for legacy reasons. In fact it praises them:

"On their face, the benefits of using exceptions outweigh the costs, especially in new projects. However, for existing code, the introduction of exceptions has implications on all dependent code. ... Because most existing C++ code at Google is not prepared to deal with exceptions, it is comparatively difficult to adopt new code that generates exceptions."

Since I'm not working on Google's old code base I do use exceptions.

Re:Investigating the Performance Overhead of C++ Exceptions by quietbritishjim on Tuesday February 11, 2020 @06:43PM (#22304209)
A couple of misconceptions here:

> It should be well-known that actually throwing an exception in C++ is extremely costly.

Unfortunately it is well known, but without really understanding what "extremely costly" means. The article shows it is expensive compared to returning from a function that does almost nothing. But what about compared to allocating some memory? Or locking a mutex? Just recently here on Hacker News I recently saw someone worryung about using an exception to close a file after doing a bunch of reads because they thought it would be too slow – but, in reality, the time taken to read a whole file is astronomical compared to throwing an exception.

> C++'s "zero-overhead" principle

Now it's possible you're right here, but just to be clear: this principle just means features don't have a cost if you don't use them. For example, if you don't need a function to be virtual then you don't have to mark it as such, so the fact that C++ supports virtual methods didn't cost you anything. But if you do choose to mark a method as virtual then there will be costs involved (memory will be taken up with the vtable and pointers to it, invocations through a pointer will take longer). Similarly, the fact that throwing exceptions isn't zero cost does not violate this principle.

The reason I say you could still be right is that there is still a memory cost to including tables of unwinding information for exceptions even if you never throw them. Perhaps that's what you meant, but the surrounding text seems to be hinting at the cost of throwing them.

Re:Investigating the Performance Overhead of C++ Exceptions by throwaway17_17 on Tuesday February 11, 2020 @07:42PM (#22304610)
I think qualification of statements is in order. I have heard the definition you gave for ‘zero-overhead’ abstractions in several places. Basically, it is often described as features which impose no cost when they are not used. However, Stroustrup uses and advocates another definition, which he discusses in his response to Sutter’s exception proposal linked by a sibling comment. When Bjarne says ‘zero-cost’ he means that some feature incurs no overhead in comparison to equivalent functionality which is hand coded. These two definitions are not equal, Bjarne’s definition (which as the originator of the term [or so I’ve heard], I tend to use as the correct case) is only concerned with asserting the overhead of language constructs compared to specific implementations of the same functionality. There is no requirement that those abstractions and features have no impact on the produced machine code or runtime requirements of not used. I wish zero-overhead meant what you say it means, but it clearly doesn’t.
Re:Investigating the Performance Overhead of C++ Exceptions by quietbritishjim on Tuesday February 11, 2020 @07:57PM (#22304694)
Interesting, thanks. I thought I got my definition from Design and Evolution of C++ by Stroustrup but it's a very long time since I read it. (It's also possible that Stroustrup has used that term in different ways over the years, but it's much more likely that I'm just mistaken.)
Re:Investigating the Performance Overhead of C++ Exceptions by throwaway17_17 on Tuesday February 11, 2020 @10:25PM (#22305463)
I think your memory is correct and that Bjarne has probably been loose with the term, I’ll check just to satisfy my curiosity later, but I do know he has been using the version I mentioned several times in the last few years.
Re:Investigating the Performance Overhead of C++ Exceptions by ncmncm on Wednesday February 12, 2020 @06:10AM (#22307844)
Some abstractions have no overhead under any circumstances, others have no runtime cost if not used. It is not inconsistent to include the former, trivially.
Re:Investigating the Performance Overhead of C++ Exceptions by throwaway17_17 on Wednesday February 12, 2020 @10:35AM (#22309613)
But my point in making the distinction is that Stroustrup does not intend to say that 'zero-overhead' is equal to 'no runtime cost if not used'. Stroustrup favors the following:

'zero-overhead' for some feature is equal to 'no runtime overhead above what one would incur from coding the feature yourself.

That definition explicitly does not include the concept that 'zero-overhead' features carry no cost when not used. In fact, the entire point of Bjarne discussing what "zero-cost" means in his response to Sutter's exception proposal, is to state that for C++ (which originated the term) "zero-cost"/zero-overhead does not mean that language features do not incur cost by inclusion in the language, like with exceptions. There is a cost to code during runtime if one does not explicitly remove exceptions from the language at compile time. Stroustrup's point is that this built in runtime overhead from having an exception mechanism built into C++ does not violate the language's 'zero-cost' guarantee.

Re:Investigating the Performance Overhead of C++ Exceptions by voxic11 on Wednesday February 12, 2020 @11:41AM (#22310289)
He actually seems to use the term to refer to both concepts. Quoting him

"What you don’t use, you don’t pay for. And further: What you do use, you couldn’t hand code any better."

Re:Investigating the Performance Overhead of C++ Exceptions by daemin on Wednesday February 12, 2020 @06:13AM (#22307856)
But in that case the equivalent would be manually writing out return codes (or return objects like Expected) and checking errors everywhere. Which at the moment is quite a lot faster than using exceptions. It may not be faster to write but it's quite a lot faster to run, to compile, and uses less disk space/memory for the resulting executable.

Ideally I would like to use exceptions as well, since they make the code look a lot neater and clearer, but I cannot justify their use in all places because of these non-zero costs.

Re:Investigating the Performance Overhead of C++ Exceptions by ncmncm on Wednesday February 12, 2020 @08:49PM (#22314655)
The time to compile exceptions is trivial. Templates and overload sets cost.

The time to run exceptions is a lot less than to run failure checks, except in extreme cases as in the synthetic (not to say phony) benchmark presented. If the time spent throwing matters, you're Doing It Wrong.

The branch prediction slots that failure checks burn are rare and precious: much bigger than a general purpose register, and much faster than L1 cache. Blowing your branch prediction cache has costs hard to measure, although the perf registers help some.

The only substantial cost is object-code file size, and that mainly because precious little effort has been spent to minimize it, because really hardly anybody (i.e., only embedded) cares.

Re:Investigating the Performance Overhead of C++ Exceptions by daemin on Thursday February 13, 2020 @07:32AM (#22317211)
The fact that just enabling exceptions adds a non-zero cost to the runtime of your program, even if the code itself does not use them, means that they are slower than just checking the return values. I've seen values from 5% to 15% slower runtime performance for just enabling exceptions and not even using them. I don't think removing the error checks will give you back those percentages.

The problem with proving something like this is you have to build and maintain two separate sets of code for the same project, one that uses exceptions in the correct manner, and another which does error checking to the same degree. Nobody has time to do that for a significant project.

Re:Investigating the Performance Overhead of C++ Exceptions by thedance on Tuesday February 11, 2020 @07:06PM (#22304368)
Exceptions being contrary to zero-overhead is not something that is just my opinion. Here's Herb Sutter's detailed white paper on the topic: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p070...

ETA: an uncontended mutex lock takes around 10-30ns depending on the machine. Any kind of exception is far more costly.

Re:Investigating the Performance Overhead of C++ Exceptions by quietbritishjim on Tuesday February 11, 2020 @07:43PM (#22304614)
> an uncontended mutex lock takes around 10-30ns depending on the machine.

I am grateful for this. But I do wish the article had a few more comparisons like this, up to and including things much more expensive than exceptions, so readers could make their own decisions rather than just read about how terrible exceptions are.

As another data point, I just read that a Linux system call that does no actual work takes about 250ns, so about a fifth of the time for an exception from the article. Of course that's a totally unknown machine that could be much slower or faster than the one used for the article's benchmark. But I still found it interesting that they're the same order of magnitude – I hadn't expected exceptions to be quite that slow.

Re:Investigating the Performance Overhead of C++ Exceptions by je42 on Tuesday February 11, 2020 @11:57PM (#22305923)
Herb Sutter also has presentation on this: https://www.youtube.com/watch?v=ARYP83yNAWk
Re:Investigating the Performance Overhead of C++ Exceptions by qeqeqeqe on Tuesday February 11, 2020 @07:20PM (#22304466)
Bjarne Stroustrup wrote a rebuttal to that proposal http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p194...
Re:Investigating the Performance Overhead of C++ Exceptions by thedance on Tuesday February 11, 2020 @07:44PM (#22304616)
Stroustrup constructs a bit of a false dichotomy there. He presents the choice between exceptions and explicit error propagation and checking, but there is a third way. If the allocator is simply infallible and std::bad_alloc just doesn't exist, and the program terminates on allocation failure instead, then you need neither exceptions nor error codes. Since std::bad_alloc is such a prominent root cause of all exceptions, and since it's preposterous to believe a program can continue after the global allocator stops working, this turns out to be a dramatic simplification of the overall program. Once you get rid of allocator exceptions it's not a big mental leap to just decide to get rid of all of them.
Re:Investigating the Performance Overhead of C++ Exceptions by usrnm on Tuesday February 11, 2020 @11:49PM (#22305894)
But std::bad_alloc does exist and it's possible and sometimes necessary to write correct software that's able to handle allocation errors. What we probably need is some sort of a compiler switch, but it will significantly complicate writing generic multi-purpose libraries
Re:Investigating the Performance Overhead of C++ Exceptions by thedance on Tuesday February 11, 2020 @11:59PM (#22305931)
bad_alloc doesn't just naturally spring into being. If you override operator new, your implementation may not use it (for example tcmalloc does not throw if it can't allocate, it logs a message and terminates the program). Many systems of the type you mention, embedded control systems and the like where correctness actually matters, don't use new and delete anyway. They often use placement new with space statically allocated at program startup. These are the same kinds of projects that often decide to not use exceptions.
Re:Investigating the Performance Overhead of C++ Exceptions by ncmncm on Wednesday February 12, 2020 @12:46AM (#22306168)
When the global allocator fails, you might not be able to do much... except set a flag, and free a big block of memory that was reserved against just such an event.

Then the program can do whatever cleanup is warranted, maybe freeing up a variety of other resources, and then maybe re-reserve that block, and forge ahead.

But when you actually care about performance, you often are not using the global allocator. A local allocation failure is nothing to panic over. Generally, only the higher level code -- where the handler is -- knows, or needs to care, what kind of allocator failed. The low-level code gets to just bail out, as it should.

Re:Investigating the Performance Overhead of C++ Exceptions by hoseja on Wednesday February 12, 2020 @03:12AM (#22306899)
You could also have just tried to allocate 42 terabytes of memory and have a well defined strategy for what to do in case this fails...
Re:Investigating the Performance Overhead of C++ Exceptions by daemin on Wednesday February 12, 2020 @06:09AM (#22307837)
Yeah, but in that case you would use your own allocator fit for this purpose and not just new or malloc.
Re:Investigating the Performance Overhead of C++ Exceptions by jfkebwjsbx on Tuesday February 11, 2020 @09:06PM (#22305095)
bad_alloc does not mean the allocator has stopped working. It only means that a particular allocation cannot be served.

And there are plenty of other root causes for exceptions in real programs, not just allocations.

That does not mean one needs exceptions, though.

Re:Investigating the Performance Overhead of C++ Exceptions by ncmncm on Tuesday February 11, 2020 @07:29PM (#22304522)
Contended mutex locks, of course, may take far, far longer than 30ns, and 30 nanoseconds is an eternity, enough time to run 500 instructions on a modern CPU.

Herb Sutter is, reliably, always right on his facts, but always mistaken on his opinions.

Re:Investigating the Performance Overhead of C++ Exceptions by qeqeqeqe on Tuesday February 11, 2020 @07:21PM (#22304472)
I suggest that people read Bjarne Stroustrup's recent paper on why exceptions are necessary to see the counter point http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p194...
Re:Investigating the Performance Overhead of C++ Exceptions by dana321 on Tuesday February 11, 2020 @03:59PM (#22302775)
Its unrolling the stack, whatever could go wrong?.. Its only expensive when you throw an exception.

They should only be used in exceptional circumstances, but they appear to be littered among libraries for everything from telling the caller that the end of file has occurred to a connection timing out.

Re:Investigating the Performance Overhead of C++ Exceptions by thedance on Tuesday February 11, 2020 @04:04PM (#22302835)
The cost comes from having to track what automatic and temporary objects have been created and attaching them to the exception context so you can destroy them if an exception is thrown. Another cost is having to track which base classes of a derived class have already been constructed when the derived constructor throws. You get noticeably better generated code when the compiler can skip all that junk.
Re:Investigating the Performance Overhead of C++ Exceptions by AnimalMuppet on Tuesday February 11, 2020 @04:47PM (#22303260)
Wait a minute.

> The cost comes from having to track what automatic and temporary objects have been created and attaching them to the exception context so you can destroy them if an exception is thrown.

Doesn't it have to do that anyway, in case you return from a function, or break from inside a loop? Anytime you can leave a scope, it has to be able to do that.

> Another cost is having to track which base classes of a derived class have already been constructed when the derived constructor throws.

All of them have been constructed before you begin the derived constructor.

Re:Investigating the Performance Overhead of C++ Exceptions by thedance on Tuesday February 11, 2020 @05:14PM (#22303531)
Thanks for holding the discussion to exact standards. What I meant about the base class constructors is the compiler must generate a derived-class constructor that can unwind the completely constructed base in case the derived class throws, not to mention the ability to destroy constructed subobjects with non-trivial destructors in case one of _their_ constructors throws. When your project decides to outlaw exceptions then none of these events are even possible and the compiler will generate a much more compact and infallible constructor.

As for leaving the scope, you're right again and I was unclear. The problem is you are destroying automatic objects while returning from a scope and one of them throws. Now you have extra code and extra branches for all of that. The extra ways of exiting a scope generally bloat up the program, and the size and complexity of a function can prevent it from being inlined or otherwise optimized by the compiler. These are systemic performance concerns that won't just show up as hot spots on a profile.

Re:Investigating the Performance Overhead of C++ Exceptions by AnimalMuppet on Tuesday February 11, 2020 @06:51PM (#22304270)
Ah, yes, I wasn't thinking about throws during destructors. IIRC, that's considered bad form but not forbidden, and so a compiler would have to handle that. (Feel free to correct if I have that wrong.)

As to your first paragraph: That's just calling the base class's destructor if the derived class's constructor throws. That's easy - that's what the base class's destructor is for. It's essentially one function call. The harder part (or so it seems to me) is correctly destroying the only-partially-constructed derived class.

Re:Investigating the Performance Overhead of C++ Exceptions by daemin on Wednesday February 12, 2020 @06:16AM (#22307875)
Throwing during destructors will generally result in a std::terminate, since you have good odds of throwing during destruction of an object that is being cleaned up as a result of an existing in progress exception.

So it is not forbidden but odds are you'll have your program terminate.

Re:Investigating the Performance Overhead of C++ Exceptions by ncmncm on Tuesday February 11, 2020 @07:31PM (#22304535)
The compiler has to handle it, but the Standard Library definitively doesn't.
Re:Investigating the Performance Overhead of C++ Exceptions by gpderetta on Tuesday February 11, 2020 @07:31PM (#22304538)
while there is extra code, there should be no extra branches in the successful case. The exceptional code path is reached during unwind by comparing the IP of the throwing call with a per stack frame table (recursively walking up the stack). Also the extra code will be extremely cold, at the limit not even paged in from disk (which of course might make the first time an exception is thrown an explicit path extremely costly)
Re:Investigating the Performance Overhead of C++ Exceptions by UncleMeat on Tuesday February 11, 2020 @04:47PM (#22303267)
The compiler has to generate code that works when exceptions are thrown. This limits some optimizations and adds overhead even if nothing happens at runtime.
Re:Investigating the Performance Overhead of C++ Exceptions by TeMPOraL on Tuesday February 11, 2020 @04:03PM (#22302814)
I don't recall NASA outright banning C++ exceptions - especially not organization-wide. Code running on space hardware has very specific risk profile, and AFAIK NASA dislikes exceptions there because they add risk to code (without a mechanism like Java's checked exceptions it's too easy to add a code path that can generate an unhandled exception, terminating the program).
Re:Investigating the Performance Overhead of C++ Exceptions by thedance on Tuesday February 11, 2020 @04:07PM (#22302854)
I'm sure it varies from one group to the other. This CppCon talk from 2014 says no exceptions are permitted in mars rover flight software.

https://github.com/CppCon/CppCon2014/blob/master/Presentatio...

Re:Investigating the Performance Overhead of C++ Exceptions by TeMPOraL on Tuesday February 11, 2020 @04:47PM (#22303265)
Yeah, but the slides don't give a reason why; the only hint is a prior slide mentioning the "historic arguments against using C++ in flight", namely "Exceptions: too much uncertainty, difficult to validate all possible control paths". And that has nothing to do with performance.
Re:Investigating the Performance Overhead of C++ Exceptions by klingonopera on Tuesday February 11, 2020 @04:56PM (#22303339)
ZeroMQ's author has written a wonderful article about how he should've picked C in place of C++ in a mission-critical setting, even despite personally preferring C++ himself.

http://250bpm.com/blog:4

Re:Investigating the Performance Overhead of C++ Exceptions by Fredej on Wednesday February 12, 2020 @04:38AM (#22307364)
This is an interesting post, definitely! However, as it was posted in 2012 I feel like some of his concerns have been addressed in newer versions of C++.

Instead of having a Constructor + init method you could have a static create function which returns an optional or a pair.

I have a hard time seeing in what case you would want to throw in a destructor though? Maybe I'm just writing a different kind of code :)

Re:Investigating the Performance Overhead of C++ Exceptions by TeMPOraL on Wednesday February 12, 2020 @04:51AM (#22307452)
> I have a hard time seeing in what case you would want to throw in a destructor though? Maybe I'm just writing a different kind of code :)

I can't imagine that case either - but what I can imagine is that your destructor calls a function that calls a function ... that calls a function you didn't realize can throw.

Re:Investigating the Performance Overhead of C++ Exceptions by sitkack on Tuesday February 11, 2020 @09:11PM (#22305123)
I really enjoy examples of analysis contravening ones opinions. We rationalize far too often.
Re:Investigating the Performance Overhead of C++ Exceptions by humanrebar on Tuesday February 11, 2020 @09:24PM (#22305173)
Well, mission critical software has to meet latency requirements, but it has to do so in a way that's provably bounded. In some ways, it's actually worth being a little slower if it's easier to prove you meet latency requirements.

Point being it's not entirely orthogonal to "performance".

Re:Investigating the Performance Overhead of C++ Exceptions by pjmlp on Wednesday February 12, 2020 @03:12AM (#22306891)
C++ had such mechanism before Java even, but it wasn't properly implemented, thus it got deprecated and eventually removed.

However value type exceptions might re-introduce it, just in a different form, with luck on C++23.

Re:Investigating the Performance Overhead of C++ Exceptions by gpderetta on Wednesday February 12, 2020 @05:01AM (#22307505)
C++ had runtime checked exceptions, which aside for the except/noexcept case, were pretty useless (and never implemented by MSVC).

I'm a huge fan of checked exception, given a type system powerful enough to parametrize over them (C++ should be more than capable), so I'm looking forward to the development. Stroustrup is not a fan though and he might kill the effort.

Re:Investigating the Performance Overhead of C++ Exceptions by pjmlp on Wednesday February 12, 2020 @10:02AM (#22309300)
I imagine that if value type exceptions get added, they will be exposed in the type system just like noexcept is.
Re:Investigating the Performance Overhead of C++ Exceptions by gpderetta on Wednesday February 12, 2020 @11:53AM (#22310405)
oh, yes. As far as I can tell, these static exceptions are basically syntactic sugar over an either<T, Except> return type, possibly with a custom ABI that stores the discriminant implicitly in a flag register (so on the call side you do not even need to load the discriminant and compare it and instead directly do a JMPcc ).
Re:Investigating the Performance Overhead of C++ Exceptions by boring_twenties on Tuesday February 11, 2020 @04:04PM (#22302829)
Not using them is insufficient, they should be disabled at compile time. IMHO, of course.
Re:Investigating the Performance Overhead of C++ Exceptions by kevin_thibedeau on Tuesday February 11, 2020 @05:08PM (#22303451)
Now what happens when new or STL throws something?
Re:Investigating the Performance Overhead of C++ Exceptions by thedance on Tuesday February 11, 2020 @07:09PM (#22304392)
When you disable exceptions anything that throws calls std::terminate instead. It's actually great.
Re:Investigating the Performance Overhead of C++ Exceptions by pansa2 on Wednesday February 12, 2020 @03:12AM (#22306898)
Is this automatic, or do you need to set it up somehow? `set_new_handler`?
Re:Investigating the Performance Overhead of C++ Exceptions by thedance on Wednesday February 12, 2020 @02:27PM (#22311898)
The standard doesn't give advice about how to break features of the standard, so disabling exceptions is a non-standard feature of the implementation. If you're planning to disable exceptions you'd better read the docs that come with your compiler.
Re:Investigating the Performance Overhead of C++ Exceptions by toolslive on Wednesday February 12, 2020 @06:16AM (#22307877)
It's even so well known that this infects thinking about exceptions in other languages. However, there are languages where throwing of an exception is as cheap as any other function call (fe when they are compiled via the so called "double barrelled continuation style" strategy)
Re:Investigating the Performance Overhead of C++ Exceptions by cmrdporcupine on Tuesday February 11, 2020 @05:00PM (#22303377)
I believe the exception ban at Google these days is justified more on the grounds that integrating with existing code would be problematic, rather than on performance grounds. I seem to remember reading something to that effect.
Re:Investigating the Performance Overhead of C++ Exceptions by billti on Tuesday February 11, 2020 @06:59PM (#22304318)
Their coding guidelines on the topic lay out the pros/cons and ultimate reasoning pretty well: https://google.github.io/styleguide/cppguide.html#Exceptions
Re:Investigating the Performance Overhead of C++ Exceptions by thedance on Tuesday February 11, 2020 @07:57PM (#22304695)
That may be the explanation they've settled on but there are build artifacts at that company which would be impossible to link without -fno-exceptions, so there are also practical problems.
Re:Investigating the Performance Overhead of C++ Exceptions by ncmncm on Wednesday February 12, 2020 @10:58AM (#22309852)
This is correct. Google have many, many million lines of casually exception-unsafe code they cannot afford to fix, so any rationalization is only that. The choice is off the table.