| 
    
        |  | Re: Vlists, Stacks and Hash-Tables | Posted: Dec 9, 2005 1:43 PM |  |  
        | > I do not see an algorithmic reason why index access should > be an order of magnitude faster for your vlist than for
 > std::deque. Both need to find the corresponding buffer and
 > offset.
 
 Finding the corresponding buffer for VList is faster because half of the items are in the first buffer. So 50% of the time it simply has to do one subscript operation. 25% of the time it has to move to the second buffer and do a subscript operation, and so on. The STLPort 4.6.2 implementation executes the following code:
 
 
 
 template <class _Tp>
 struct _Deque_iterator_base {
 
 enum _Constants {
 _blocksize = _MAX_BYTES,
 __buffer_size = (sizeof(_Tp) < (size_t)_blocksize ?
 ( (size_t)_blocksize / sizeof(_Tp)) : size_t(1))
 };
 
 typedef random_access_iterator_tag iterator_category;
 
 typedef _Tp value_type;
 typedef size_t size_type;
 typedef ptrdiff_t difference_type;
 
 typedef value_type** _Map_pointer;
 
 typedef _Deque_iterator_base< _Tp > _Self;
 
 value_type* _M_cur;
 value_type* _M_first;
 value_type* _M_last;
 _Map_pointer _M_node;
 
 _Deque_iterator_base(value_type* __x, _Map_pointer __y)
 : _M_cur(__x), _M_first(*__y),
 _M_last(*__y + __buffer_size), _M_node(__y) {}
 _Deque_iterator_base() : _M_cur(0), _M_first(0), _M_last(0), _M_node(0) {}
 
 void _M_advance(difference_type __n)
 {
 difference_type __offset = __n + (_M_cur - _M_first);
 if (__offset >= 0 && __offset < difference_type(__buffer_size))
 _M_cur += __n;
 else {
 difference_type __node_offset =
 __offset > 0 ? __offset / __buffer_size
 : -difference_type((-__offset - 1) / __buffer_size) - 1;
 _M_set_node(_M_node + __node_offset);
 _M_cur = _M_first +
 (__offset - __node_offset * difference_type(__buffer_size));
 }
 }
 
 void _M_set_node(_Map_pointer __new_node) {
 _M_last = (_M_first = *(_M_node = __new_node)) + difference_type(__buffer_size);
 }
 };
 
 Of course there are many different ways to implement a deque, I was only comparing to STLPort 4.6.2.
 
 > I suspect the difference is caused by runtime
 > checks in the stlport implementation.
 
 I use NDEBUG to turn off runtime checking. I have provided the source code on my website, and you can verify the code yourself.
 
 > I just browsed through the code, but I noticed the
 > following:
 > inside iterator::operator+=(), there is technically
 > undefined behaviour if the pos pointer is increased beyond
 > the end of the buffer. The same goes for operator-=()
 
 That is common practice for random access iterators (behaviour similar to raw pointers), but not neccessarily a best practice.
 
         |  |