Boost logo

Boost :

From: Achilleas Margaritis (axilmar_at_[hidden])
Date: 2007-09-20 07:01:08


Thanks for the tip, I will look into it.

I've done a small benchmark to check how fast an std::list is compared
to cppgc::_list, and the difference is very large.

std::list duration = 4929.17
_list duration = 3.40211

Perhaps the std::list requires a special allocator class to become as
efficient as an intrucive list.

The benchmark (which can be wrong - I am not a specialist) is attached
as a file.

Joaquín Mª López Muñoz wrote:
>
> Achilleas Margaritis ha escrito:
>
>> I think std::list is slower than my list (I could be wrong of course),
>> because it allocates memory from the heap for each node, whereas my list
>> requires the elements to have the node embedded in them, and so blocks
>> are also nodes.
>
> Maybe you can then replace your private intrusive list with Boost.Intrusive:
>
> http://igaztanaga.drivehq.com/intrusive
>
> which is already included in the SVN trunk.
>
> Joaquín M López Muñoz
> Telefónica, Investigación y Desarrollo
>
> _______________________________________________
> Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
>


#include <iostream>
#include <list>
using namespace std;

#ifdef WIN32

#include <windows.h>

class PerformanceCounter {
public:
    PerformanceCounter() {
        QueryPerformanceFrequency(&_frequency);
    }
    
    void start() {
        QueryPerformanceCounter(&_start);
    }

    void end() {
        QueryPerformanceCounter(&_end);
    }
    
    double duration() const {
        return (((double)_end.QuadPart - (double)_start.QuadPart) / (double)_frequency.QuadPart) * 1000.0;
    }

private:
    LARGE_INTEGER _frequency;
    LARGE_INTEGER _start;
    LARGE_INTEGER _end;
};

#else

#include <sys/time.h>

class PerformanceCounter {
public:
    PerformanceCounter() {
    }
    
    void start() {
        _start = clock();
    }

    void end() {
        _end = clock();
    }
    
    double duration() const {
        return _end - _start;
    }

private:
    double _start;
    double _end;
    
    static double clock(void) {
        struct timeval t;
        struct timezone tz;
        if (gettimeofday( &t, &tz ) == -1) return 0;
        return (t.tv_sec * 1000 + t.tv_usec / 1000);
    }
};

#endif //WIN32

//a double-linked list class where nodes have embedded links to previous/next items
template <class T> struct _list {
public:
    //initializes the object; use instead of constructor;
    //the data structure is allocated statically and initialized manually;
    //it solves the problem of initialization order of static data
    inline void _init() {
        _begin = &_begin_elem;
        _end = &_end_elem;
        _begin_elem._list_next = _end;
        _end_elem._list_prev = _begin;
    }

    inline void _cleanup() {
    }

    //get first element
    inline T * begin() const {
        return _begin_elem._list_next;
    }

    //get end element
    inline const T *end() const {
        return &_end_elem;
    }

    //adds an element as the last entry
    inline void add(T *elem) {
        elem->_list_next = &_end_elem;
        elem->_list_prev = _end_elem._list_prev;
        _end_elem._list_prev->_list_next = elem;
        _end_elem._list_prev = elem;
    }

    //removes an element
    inline void remove(T *elem) {
        elem->_list_prev->_list_next = elem->_list_next;
        elem->_list_next->_list_prev = elem->_list_prev;
    }

private:
    T *_begin;
    T *_end;
    T _begin_elem;
    T _end_elem;
};

class Foo1 {
public:
    Foo1 *_list_next, *_list_prev;
    int i, j;
    
    Foo1() {
        _list_next = _list_prev = 0;
        i = j = 0;
    }
};

class Foo2 {
public:
    int i, j;
    
    Foo2() {
        i = j = 0;
    }
};

int main() {
    typedef _list<Foo1> foo1_list_t;
    typedef std::list<Foo2 *> foo2_list_t;
    
    foo1_list_t foo1_list;
    foo1_list._init();
    
    foo2_list_t foo2_list;

    PerformanceCounter pc;
    
    static const size_t _MAX = 100000;
    static Foo1 foo1[_MAX];
    static Foo2 foo2[_MAX];
    
    pc.start();
    for(size_t i = 0; i < _MAX; ++i) {
        foo2_list.push_back(foo2 + i);
    }
    for(foo2_list_t::iterator it = foo2_list.begin(); it != foo2_list.end(); ++it) {
        Foo2 *f = *it;
        ++f->i;
        ++f->j;
    }
    while (!foo2_list.empty()) {
        foo2_list.pop_front();
    }
    pc.end();
    cout << "std::list duration = " << pc.duration() << endl;

    pc.start();
    for(size_t i = 0; i < _MAX; ++i) {
        foo1_list.add(foo1 + i);
    }
    for(Foo1 *f = foo1_list.begin(); f != foo1_list.end(); f = f->_list_next) {
        ++f->i;
        ++f->j;
    }
    while (foo1_list.begin() != foo1_list.end()) {
        foo1_list.remove(foo1_list.begin());
    }
    pc.end();
    cout << "_list duration = " << pc.duration() << endl;

    getchar();
    return 0;
}


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