nothrow by default
Gregor Mückl
gregormueckl at gmx.de
Sun Jan 5 12:27:11 UTC 2020
On Sunday, 5 January 2020 at 10:32:23 UTC, Johannes Pfau wrote:
> The benefits now are simple: Implementation code / memory
> overhead is
> almost zero, no TypeInfo required, trivial to implement on
> embedded
> systems, .... At the same time, exceptions bubble up
> properly so they
> can't be accidentially unhandled. The runtime overhead in
> the success
> case is obviously higher than for some exception systems,
> but it's
> only a simple conditional jump. It is cheaper than manual
> error codes,
> as we reuse the same registers for return value and error
> code,
> benefitting register allocation. Error propagation also uses
> the same
> registers in all functions and is therefore very efficient.
>
Consulting Agner Fox's microarchitecture manual, current Intel
CPUs still take a performance hit when encountering code with a
high density of conditional branches. They are sensitive to the
number of branch instructions per cache line. I've seen GCC pad
code with NOPs for that reason. AMD's branch predictor, on the
other hand, is described as perceptron that fares better with
repeated patterns of branches and isn't tied to the cache. Branch
mispredictions still hurt a lot (~20 cycles). All
microcontrollers I'm familiar stall their pipeline on every
branch if they're pipelined at all.
Moving error handling overhead back into the common/fast code
path is a step backwards in those cases where performance
matters. Desktops and servers can absolutely afford to have the
data overhead associated with exceptions and they benefit the
most from out of band error handling.
It would be nice to have choice here.
> 2) (Optional): Herb arguest that because of throw ... it is
> easy to spot
> where an exception originates, but it's more difficult to
> find where
> an exception was propagated. As a solution,
> whenever calling a throws function, the calls should be
> preceeded by
> throw:
> auto value = throw myThrowingFunction();
> Here throw does essentially this: If myThrowingFunction
> threw, rethrow
> the exception. Otherwise return the return value.
>
I hope that this doesn't require code to have a throw keyword in
every other line. Imagine outer functions of some algorithm where
the inner functions have a lot of opportunity to fail:
auto result1 = throw step1();
auto result2 = throw step2(result1);
// etc...
The value of the keyword decreases rapidly with the number of
occurrences.
> 3) (C++ specific): Error codes instead of exceptions, "Type
> based Errors":
> I don't really know what is meant by this "Type-Based Errors"
> terminology, seems to be a C++ marketing thing ("we do
> everything with
> types now")... The important takeaway is to not allocate
> complex
> exception objects. Use the error code and context value. If
> really
> more context than one word is necessary, it's still possible
> to stuff
> a pointer into context.
>
There's recently been a talk about error types in C++ and their
evolution:
https://www.youtube.com/watch?v=coBz_CQ1tJ8&
As with everything in C++, there's a lot of complexity.
>
> Caveats:
> * I have not thought about how exception chaining fits into all
> this.
This would require an exception to be allocated that starts the
chain. The error return value could then turn into a pointer to
that value. That's similar to how the C++ proposals return
exceptions in error value returning functions.
> * These exceptions do not naturally propagate through foreign
> language
> interfaces, although I think we don't guarantee this in D
> right now
> either.
D exceptions and C++ exception implementations are currently
quite incompatible, but the documentation still states that that
is an eventual goal of D:
https://dlang.org/spec/cpp_interface.html#exception-handling
More information about the Digitalmars-d
mailing list