|
Boost : |
Subject: Re: [boost] Boost.Outcome review - First questions
From: Emil Dotchevski (emildotchevski_at_[hidden])
Date: 2017-05-24 23:03:42
On Wed, May 24, 2017 at 2:30 PM, Niall Douglas via Boost <
boost_at_[hidden]> wrote:
> > This may be
> > true but your reasoning is still rather abstract. Does anyone have a
> > concrete program where reporting a failure by throwing would be too
> > expensive? If not, what problem are we aiming to solve with Outcome?
>
> c.f. the AFIO v1 review some years ago where my view that the cost of
> throwing an exception was irrelevant compared to a disc i/o. I was still
> panned for that design choice.
>
This is presented as a matter of opinion. I was looking for something more
objective, since I am familiar with the unsubstantiated "exceptions are
slow!!!!" attitude (my background is in video game engines and no, there
are no performance problems with throwing exceptions to report errors in
games, despite what others claim without evidence.)
> > By the way, it would be very helpful if the examples in Outcome don't
> talk
> > about failures to open files, especially if the objection to using
> > exceptions is that their performance is "unpredictable".
>
> File i/o failure can be both common and unpredictable. It's why AFIO v2
> needed a very low overhead failure handling mechanism, and I use it with
> a vengeance in afio::algorithm::* the AFIO v2 filesystem algorithms
> library. Performance, especially on NVMe SSDs, is spectacular.
>
Spectacular, compared to what? Is it spectacular because it avoids throwing
exceptions?
When I mention the unpredictability of file operations, what I mean is that
their performance is even _more_ unpredictable than the overhead of (the
work done during) stack frame unwinding. It is wrong to be concerned with
the unpredictability the performance of a throw in the case you're dealing
with I/O.
> > I agree that talking about actual compilers today is relevant and should
> be
> > considered, so when I'm discussing exception handling overhead I do mean
> > actual real world uses.
>
> In real world code, the cost of the exception throw and catch mechanism
> will be dwarfed by work done during the unwind in most cases. So for the
> average case, just go with C++ exceptions and relax.
>
> But for some users, every possible execution path needs to have a hand
> allocated CPU cycle budget. For these users, Expected or Outcome is less
> error prone than integer error codes.
>
I'm still looking for these use cases. I keep hearing they exist, I am sure
they exist, and it would be very helpful if Outcome lists a few of them and
shows how throwing exceptions fails spectacularly in these cases, rather
than talking about I/O, in which case you seem to agree it's better to
throw exceptions to report failures.
> That said, in the spirit of C++ we should think of exception handling
> > abstractly, even not considering specific ABIs. After all, we don't talk
> > about the overhead of using for loops vs. do-while, do we? It should be
> the
> > same with exceptions. If I have:
> >
> > try { throw x(); } catch( x & ) { }
> >
> > there is no reason for any exception to be actually thrown. In principle,
> > compilers should be able to see that the above is noop.
>
> Most of the time trivially obvious try...catch are turned into a branch
> to early exit by the compiler. But it's not consistent. I've seen very
> obvious trivial try...catch get turned into a full dive into the runtime
> for execution despite the obviously inlined code. I would assume an
> optimiser bug.
>
The other possibility is ABI restriction. Either way, not a problem for the
C++ definition itself.
> > From this point of view, there should be no performance difference
> between
> > returning an error code or throwing an exception, and if there is, that
> is
> > a problem of the compiler or the ABI but not of the semantics of
> exception
> > handling as defined by C++.
>
> For some users, "should" isn't enough. They want *guaranteed*.
>
It is not possible to guarantee that the optimizer will do a good job
optimizing a for loop either, that's why I said "should". If your point is
that it's more likely for a code generator to deal efficiently with a for
loop than with throw..catch, that is probably true, but I didn't think that
Outcome is designed as a workaround for the deficiencies of existing
optimizers.
Maybe all this means is that Outcome needs better examples, but I still
don't understand its motivation. Or maybe it's as simple as "some people
religiously avoid throwing exceptions and this is better than what they
would do otherwise"
Emil
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk