RE: [Boost-users] [pool] Speed of pool_allocator<>

Peter Dimov wrote:
Klaus Nowikow wrote:
template <class Allocator> double Test() { std::vector<Allocator::value_type, Allocator> Vector; boost::timer Timer;
for(int i = 0; i < NUM_ELEMENTS; ++i) { Vector.push_back(i); }
return Timer.elapsed(); }
If I read the code correctly, you don't create or delete objects. You create and delete (large) arrays of objects.
I changed the test program (see below). Now I use object_pool<> to create and destroy a number of elements (I use a vector<C*> to store them in the meantime). The results are even worse than before: new/delete: 0.08s object_pool: 25.20s Note that I created a class non_pool with an interface similar to object_pool to be able to use one function template for both tests. // MemoryPoolTest.cpp #include <boost/timer.hpp> #include <boost/pool/object_pool.hpp> #include <vector> #include <iostream> enum { NUM_ELEMENTS = 100000 , CHUNK_SIZE = NUM_ELEMENTS }; class C { int i_; char c_; }; struct Empty { }; template <class T, class U = Empty> struct non_pool // create, destroy with new and delete { explicit non_pool(int) { } T* construct() const { return new T; } void destroy(T* pT) { delete pT; } }; template <template <class, class> class Pool> double Test() { Pool<C> P(CHUNK_SIZE); boost::timer Timer; std::vector<C*> V; for(int i = 0; i < NUM_ELEMENTS; ++i) { V.push_back(P.construct()); } for(std::vector<C*>::iterator pos = V.begin(), end = V.end(); pos != end; ++pos) { P.destroy(*pos); } return Timer.elapsed(); } int main(int, char**) { std::cout << "Starting memory pool test" << std::endl; double Time; std::cout << "Allocating with new : "; Time = Test<non_pool>(); std::cout << Time << "s" << std::endl; std::cout << "Allocating with boost::object_pool<>: "; Time = Test<boost::object_pool>(); std::cout << Time << "s" << std::endl; return 0; }

Klaus Nowikow wrote:
I changed the test program (see below). Now I use object_pool<> to create and destroy a number of elements (I use a vector<C*> to store them in the meantime). The results are even worse than before:
new/delete: 0.08s object_pool: 25.20s
[...]
template <template <class, class> class Pool> double Test() { Pool<C> P(CHUNK_SIZE); boost::timer Timer;
std::vector<C*> V; for(int i = 0; i < NUM_ELEMENTS; ++i) { V.push_back(P.construct()); } for(std::vector<C*>::iterator pos = V.begin(), end = V.end(); pos != end; ++pos) { P.destroy(*pos); }
return Timer.elapsed(); }
Your test is still very unrealistic. You create a large number of objects in one batch, then destroy them afterwards. A more realistic scenario would have creation and destruction interleaved. The most accurate test would be to try Boost.Pool with your actual application and see how it affects its real-world performance. It's still possible for it to be slower, of course, but at least you'd measure the real thing.

Peter Dimov wrote:
Your test is still very unrealistic. You create a large number of objects in one batch, then destroy them afterwards. A more realistic scenario would have creation and destruction interleaved.
The most accurate test would be to try Boost.Pool with your actual application and see how it affects its real-world performance. It's still possible for it to be slower, of course, but at least you'd measure the real thing.
OTOH I could not find an application where pool_allocators outperformed Intel's small object allocator strategy. So at least with Intel's C++ compilers pool_allocator is nice to have, but gained me nothing until now. IMHO this belongs to namespace premature_optimization. Markus
participants (3)
-
Klaus Nowikow
-
Markus Werle
-
Peter Dimov