Boost logo

Boost :

Subject: Re: [boost] expected/result/etc
From: Emil Dotchevski (emildotchevski_at_[hidden])
Date: 2016-02-12 15:48:47


On Fri, Feb 12, 2016 at 1:25 AM, Michael Marcin <mike.marcin_at_[hidden]>
wrote:

> On 2/12/2016 1:39 AM, Emil Dotchevski wrote:
>
>> On Thu, Feb 11, 2016 at 9:02 PM, Michael Marcin <mike.marcin_at_[hidden]>
>> wrote:
>>
>>>
>>> But I don't want to pay for them in retail builds.
>>>
>>>
>> Good, I don't, either.
>>
>
> Sorry, I don't follow at all then.
>
> If .get() isn't specified as UB when a value is not ready how are you
> going to avoid the overhead?
>
> Specifically .get() must do *at least* an if statement before returning
> the value.
>

Calling shared_ptr::get() is always well defined. It contains no ifs.

> And I'm arguing that whether you throw or not should rarely be a question
>> of performance. If hitting the intersection limit in a raytracing program
>> leads to an invalid frame, you should report that error by throwing an
>> exception. This has zero performance cost if functions are being inlined,
>> which they are at the lowest levels of a raytracer. Generally, if you can
>> afford the "if" statement to detect the error, you can afford to throw.
>>
>>
> Sorry I don't follow.
> Are you suggesting that the raytracer should be inlined into every call
> site?
>

I avoid using inline except if the profiler tells me it's needed. If it is
needed, then I inline regardless of whether the function emits exceptions
or not.

> What I think you're saying is that where I want to write code that looks
> like:
>
>
> result<int> bar()
> {
> return std::make_error_code( std::errc::bad_address );
> }
>
> int main()
> {
> int foo;
>
> auto _foo = bar();
> if ( _foo ) {
> foo = _foo.get();
> } else {
> foo = 0;
> }
>
> return foo;
> }
>
>
> I should instead write code that looks like:
>
> int bar()
> {
> throw std::system_error(
> std::make_error_code( std::errc::bad_address ) );
> }
>
> int main()
> {
> int foo;
>
> try {
> foo = bar();
> }
> catch ( std::system_error& e )
> {
> foo = 0;
> }
>
> return foo;
> }
>
>
> And I should expect equal performance?
>

Obviously not, because you're always throwing. Throw may incur overhead,
certainly does on Windows. What I'm saying is that when you don't actually
throw, exception handling overhead occurs exactly where function call
overhead occurs, and can be eliminated completely by inlining.

In ~20 years in the video game industry I have never needed to implement my
>> own STL, and modern STL implementations are a lot better than in the old
>> days. On the other hand years ago I did have to refactor a company's
>> home-grown STL replacement to fold templates to reduce bloat, since
>> otherwise the executable was over 20 megs on a platform with 32 megs of
>> RAM. Ironically, the STL on that platform was folding the templates
>> automatically. Too bad they had it banned.
>>
>>
> Your experience differs from my own.
>
> EASTL just (officially) released to much fanfare.
> https://github.com/electronicarts/EASTL
>
> It's very easy to find performance problems in even current shipping
> standard libraries.
> 2 examples:
> See what happens when you insert a duplicate key into a std::map VS2015.
> Or look towards the 17x perf increase in iostreams float serialization
> coming in VS2015 update 2.

Yes I'm familiar with EASTL. I generally don't care how slow STL is, except
when something shows up on my radar (profiler), in which case usually the
reason is user error. Regardless, consider that if a particular use of
std::map is too slow, you don't need a faster std::map, you need a faster
implementation only for the operations needed in this particular use of
std::map. Such implementation can be a lot faster than STL or EASTL because
it isn't generic.

Emil


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk