News for hackers. Stuff that matters.
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.