Re: [boost] Boost pool allocator slower than STL allocator

Hi I've been testing out boost pool allocator, and my results shows it's slower than the STL allocator. I'm using VSNet 2005 SP1. See test code below. Also, on a separate issue, I notice the pool_allocator uses a singleton with static member in a function (Meyer's singleton). While this avoid the static construction issue, it does not free the memory until the application quits. This would work fine only POD data, if the dtor depends on a system in the application, it won't work. Shouldn't there be a pool allocator which can be used like the object_pool? Robin Test code -------- With boost pool, timing on average is (0.03) vs STL (0.02) seconds in release mode. In debug mode, its boost (0.99) vs STL (0.8) #include <boost/pool/pool_alloc.hpp> #include <iostream> #include <vector> using namespace std; class A { int x, y; public: A () : x (0), y (0) {} }; #include <windows.h> class Timer { public: Timer() { reset(); } /// reset() makes the timer start over counting from 0.0 seconds. void reset() { unsigned __int64 pf; QueryPerformanceFrequency( (LARGE_INTEGER *)&pf ); freq_ = 1.0 / (double)pf; QueryPerformanceCounter( (LARGE_INTEGER *)&baseTime_ ); } /// seconds() returns the number of seconds (to very high resolution) /// elapsed since the timer was last created or reset(). double seconds() { unsigned __int64 val; QueryPerformanceCounter( (LARGE_INTEGER *)&val ); return (val - baseTime_) * freq_; } /// seconds() returns the number of milliseconds (to very high resolution) /// elapsed since the timer was last created or reset(). double milliseconds() { return seconds() * 1000.0; } private: double freq_; unsigned __int64 baseTime_; }; int main () { Timer timer; for (int i = 0; i < 10; ++i) { // Switch allocators // typedef vector <A> VectorA; typedef vector <A, boost::pool_allocator <A> > VectorA; VectorA vectorA; double startTime = timer.seconds (); for (int jj = 0; jj < 1000000; ++jj) { vectorA.push_back (A()); } double endTime = timer.seconds (); cout << "Time taken is " << i << " - " << endTime - startTime << endl; } return 0; }
On 30/12/2007, Robin <al@cyberversion.com> wrote:
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
It seems your message got sent without any body text.

On 30/12/2007, Robin <al@cyberversion.com> wrote:
I've been testing out boost pool allocator, and my results shows it's slower than the STL allocator. I'm using VSNet 2005 SP1. See test code below.
My understanding is that the pool allocator is made for repeated allocation and deallocation of same-sized blocks, in which case the result makes sense. I think it's more intended for use with node-based containers such as list and map.

My understanding is that the pool allocator is made for repeated allocation and deallocation of same-sized blocks, in which case the result makes sense. I think it's more intended for use with node-based containers such as list and map.
I tried with list, the std::allocator is still faster typedef list <A, boost::pool_allocator <list <A>::value_type > > ListA; ListA listA; then listA.push_back (A ()); listA.pop_front (); Or with boost::shared_ptr as I need to keep a polymorphic pointer. typedef list < boost::shared_ptr <A>, boost::pool_allocator <A> > ListA; ListA listA; then listA.push_back (boost::shared_ptr <A> (new A ())); listA.pop_front (); I can't get map to compile, typedef map <string, A, boost::pool_allocator <std::map <string,A>::value_type >
MapA; MapA mapA;
mapA.insert (make_pair ("test",A ())); VC8 balks at this line at the xutility comparision predicate header. It compiles fine with the std allocator. Am I using pool incorrectly? Robin
On 30/12/2007, Robin <al@cyberversion.com> wrote:
I've been testing out boost pool allocator, and my results shows it's slower than the STL allocator. I'm using VSNet 2005 SP1. See test code below.
My understanding is that the pool allocator is made for repeated allocation and deallocation of same-sized blocks, in which case the result makes sense. I think it's more intended for use with node-based containers such as list and map.

Robin wrote:
My understanding is that the pool allocator is made for repeated allocation and deallocation of same-sized blocks, in which case the result makes sense. I think it's more intended for use with node-based containers such as list and map.
I tried with list, the std::allocator is still faster
typedef list <A, boost::pool_allocator <list <A>::value_type > > ListA; ListA listA;
then
listA.push_back (A ()); listA.pop_front ();
Or with boost::shared_ptr as I need to keep a polymorphic pointer.
typedef list < boost::shared_ptr <A>, boost::pool_allocator <A> > ListA; ListA listA;
then
listA.push_back (boost::shared_ptr <A> (new A ())); listA.pop_front ();
I can't get map to compile,
typedef map <string, A, boost::pool_allocator <std::map <string,A>::value_type >
MapA; MapA mapA;
mapA.insert (make_pair ("test",A ()));
VC8 balks at this line at the xutility comparision predicate header. It compiles fine with the std allocator.
Am I using pool incorrectly?
Robin
On 30/12/2007, Robin <al@cyberversion.com> wrote:
I've been testing out boost pool allocator, and my results shows it's slower than the STL allocator. I'm using VSNet 2005 SP1. See test code below.
My understanding is that the pool allocator is made for repeated allocation and deallocation of same-sized blocks, in which case the result makes sense. I think it's more intended for use with node-based containers such as list and map.
From the docs: http://www.boost.org/libs/pool/doc/interfaces/pool_alloc.html The Fast Pool Allocator ... If you are seriously concerned about performance, use fast_pool_allocator when dealing with containers such as std::list, and use pool_allocator when dealing with containers such as std::vector. Jeff Flinn

on Sun Dec 30 2007, Robin <al-AT-cyberversion.com> wrote:
My understanding is that the pool allocator is made for repeated allocation and deallocation of same-sized blocks, in which case the result makes sense. I think it's more intended for use with node-based containers such as list and map.
I tried with list, the std::allocator is still faster
typedef list <A, boost::pool_allocator <list <A>::value_type > > ListA; ListA listA;
then
listA.push_back (A ()); listA.pop_front ();
Or with boost::shared_ptr as I need to keep a polymorphic pointer.
typedef list < boost::shared_ptr <A>, boost::pool_allocator <A> > ListA; ListA listA;
then
listA.push_back (boost::shared_ptr <A> (new A ())); listA.pop_front ();
I can't get map to compile,
typedef map <string, A, boost::pool_allocator <std::map <string,A>::value_type >
MapA; MapA mapA;
mapA.insert (make_pair ("test",A ()));
VC8 balks at this line at the xutility comparision predicate header. It compiles fine with the std allocator.
Am I using pool incorrectly?
Yes. list<A, whateverallocator> doesn't allocate blocks of size sizeof(list<A>::value_type). Instead, it allocates a (larger) node size that you can't know without looking at list's implementation details. If you want to make an efficient pool allocator, you need its allocation size to be the same as that of the nodes being allocated. -- Dave Abrahams Boost Consulting http://boost-consulting.com
participants (4)
-
David Abrahams
-
Jeff Flinn
-
Robin
-
Scott McMurray