Increase distribution of pool allocators than new

So, I created a memory_pools container memory_pools based on the boost pool:

memory_pools.hpp

 #ifndef MEMORY_POOL_HPP # define MEMORY_POOLS_HPP // boost # include <boost/pool/pool.hpp> # include <boost/unordered_map.hpp> template<typename ElementType> class memory_pools { public: template <typename> friend class memory_pools; private: using pool = boost::pool<>; public: using value_type = ElementType; using pointer = value_type*; using const_pointer = const value_type*; using reference = value_type&; using const_reference = const value_type&; using size_type = pool::size_type; using difference_type = pool::difference_type; public: template<typename OtherElementType> struct rebind { using other = memory_pools<OtherElementType>; }; public: memory_pools(); template<typename SourceElement> memory_pools(const memory_pools<SourceElement>&); public: pointer allocate(const size_type n); void deallocate(const pointer ptr, const size_type n); template<typename... Args> void construct(pointer, Args...); void destroy(pointer); public: bool operator==(const memory_pools&); bool operator!=(const memory_pools&); private: using pools_map = boost::unordered_map<std::size_t, std::shared_ptr<pool>>; private: std::shared_ptr<pools_map> pools_map_; std::shared_ptr<pool> pool_; }; # include <memory_pools.ipp> #endif 

memory_pools.ipp

 #ifndef MEMORY_POOLS_IPP # define MEMORY_POOLS_IPP template<typename ElementType> memory_pools<ElementType>::memory_pools() : pools_map_(std::make_shared<pools_map> (pools_map { std::make_pair (sizeof(ElementType), make_shared<pool>(sizeof(ElementType))) })), pool_(pools_map_->at(sizeof(ElementType))) { } template<typename ElementType> template<typename SourceElement> memory_pools<ElementType>::memory_pools (const memory_pools<SourceElement>& rebinded_from) : pools_map_(rebinded_from.pools_map_), pool_(pools_map_->insert (std::make_pair(sizeof(ElementType), make_shared<pool>(sizeof(ElementType)))).first->second) { } template<typename ElementType> typename memory_pools<ElementType>::pointer memory_pools<ElementType>::allocate (const size_type n) { pointer ret = static_cast<pointer>(pool_->ordered_malloc(n)); if ((!ret) && n) throw std::bad_alloc(); return (ret); } template<typename ElementType> void memory_pools<ElementType>::deallocate (const pointer ptr, const size_type n) { pool_->ordered_free(ptr, n); } template<typename ElementType> template<typename... Args> void memory_pools<ElementType>::construct(pointer ptr, Args... args) { new (ptr) ElementType(std::forward<Args>(args)...); } template<typename ElementType> void memory_pools<ElementType>::destroy(pointer ptr) { ptr->~ElementType(); } template<typename ElementType> bool memory_pools<ElementType>::operator==(const memory_pools& rhs) { return (pools_map_ == rhs.pools_map_); } template<typename ElementType> bool memory_pools<ElementType>::operator!=(const memory_pools& rhs) { return (pools_map_ != rhs.pools_map_); } #endif 

Then when I test it using:

 #include <memory_pools.hpp> int main(void) { using pools_type = memory_pools<std::pair<const int, int>>; pools_type pools; boost::unordered_map<int, int, boost::hash<int>, std::equal_to<int>, pools_type> map; //boost::unordered_map<int, int, boost::hash<int>, std::equal_to<int>> map; for (unsigned int i = 0; i < 20000; ++i) { map[i] = i + 1; } return (0); } 

From clang3.5 on macOSX 10.10 I got:

 $ time ./a.out real 0m1.873s user 0m1.850s sys 0m0.009s 

If I run:

 #include <memory_pools.hpp> int main(void) { using pools_type = memory_pools<std::pair<const int, int>>; pools_type pools; //boost::unordered_map<int, int, boost::hash<int>, std::equal_to<int>, pools_type> map; boost::unordered_map<int, int, boost::hash<int>, std::equal_to<int>> map; for (unsigned int i = 0; i < 20000; ++i) { map[i] = i + 1; } return (0); } 

I have:

 $ time ./a.out real 0m0.019s user 0m0.016s sys 0m0.002s 

Question

Is memory allocation using the boost pool supposedly slow, or is my test invalid for some reason?


EDIT

After Carmeron's comment, I added the -O3 and -DNDEBUG , now I have:

 $time ./a.out real 0m0.438s user 0m0.431s sys 0m0.003s 

for version memory_pools and:

 $ time ./a.out real 0m0.008s user 0m0.006s sys 0m0.002s 

for the standard version of the distributor.

Question

The question still remains, is it normal slower?

+7
c ++ performance performance-testing boost-pool
source share
1 answer

I have never used Boost pool code or even read it. But I know some things about memory pools in general, and I would not expect the memory pool in your test to surpass malloc.

To understand this, you must first understand how malloc and free are implemented, if you have not already done so. The answers to this question seem to give a pretty good summary: How do malloc () and free () work?

Memory fragmentation is a difficult problem for malloc() and free() , and there is no easy, quick fix. But it is much simpler if you can guarantee that all your allocations are the same size: this is how memory pools can be won. But your test does not require a lot of memory fragmentation and probably does not free up much memory. Thus, malloc() wins in this test, and the pools are lost. To clarify your test, you can mix a bunch of deletions, for example:

 // Allocate 10,000 things // Loop 10 times: // Allocate 1,000 things // Delete 1,000 things 

Having said all this, if you really want to know why a particular piece of code works the way you do it, you should profile it. It's useful to come up with theories about why a piece of code behaves in a certain way, but you should also test your theories.

+6
source share

All Articles