
Peter Dimov skrev:
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.
Thanks for the analysis. But don't you agree that is is worth avoiding the check for the buffer being full when this is possible? -Thorsten