'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.
"What you don’t use, you don’t pay for. And further: What you do use, you couldn’t hand code any better."
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.
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.
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.
ETA: an uncontended mutex lock takes around 10-30ns depending on the machine. Any kind of exception is far more costly.
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.
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.
And there are plenty of other root causes for exceptions in real programs, not just allocations.
That does not mean one needs exceptions, though.
Herb Sutter is, reliably, always right on his facts, but always mistaken on his opinions.
> 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.