Boost logo

Boost :

Subject: Re: [boost] [utility] new auto_buffer class --- RFC
From: Peter Dimov (pdimov_at_[hidden])
Date: 2009-03-03 12:15:22


Thorsten Ottosen:
> Christopher Jefferson skrev:
>>
>> On 2 Mar 2009, at 21:32, Thorsten Ottosen wrote:
>
>>> So did I in a real-time ray-tracing application. The difference was a
>>> deal-breaker.
>>>
>>
>> Interesting, I wouldn't have expected to get such a big difference. I
>> certainly have no trouble with a push_back_unchecked(), but think
>> push_back() should do what it does in vector and friends.
>
> Right.

The reason for the apparent discrepancy is probably because Thorsten is
comparing Dinkumware's vector::push_back against his unchecked
auto_buffer::push_back, and erroneously attributing the difference in
performance to the fact that push_back is not inlined (false; push_back
itself is easily inlined by all compilers I know of) and to the presence of
the capacity check.

In fact, the problem lies in the Dinkumware implementation of push_back, not
in the interface requirements. Here's the older version (VC6):

 void push_back(const _Ty& _X)
  {insert(end(), _X); }

Why this underperforms should be obvious.

Here's the more recent version (VC7.1-9.0):

 void push_back(const _Ty& _Val)
  { // insert element at end
  if (size() < capacity())
   _Mylast = _Ufill(_Mylast, 1, _Val);
  else
   insert(end(), _Val);
  }

This is somewhat better, but still suboptimal, for two reasons. One, it
diligently goes through Alloc::construct, using two nested function calls
for that; two, size() and capacity() hide two divisions on sizeof(T).

Changing the implementation to check for _Mylast < _Myend and inlining the
_Ufill call by hand improves the performance of vector<int>::push_back
dramatically, and the unchecked version no longer has any significant
advantage.


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