Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Boost池分配器比new慢_C++_Performance_Performance Testing_Boost Pool - Fatal编程技术网

C++ Boost池分配器比new慢

C++ Boost池分配器比new慢,c++,performance,performance-testing,boost-pool,C++,Performance,Performance Testing,Boost Pool,因此,我基于boost pool创建了这个容器分配器内存池类: 内存池.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:

因此,我基于boost pool创建了这个容器分配器
内存池
类:

内存池.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
#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

鉴于当我启动时:

#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);
}

问题

使用boost池的内存分配应该是那么慢,还是我的测试由于某种原因无效


编辑

在的评论之后,我添加了
-O3
-DNDEBUG
标志,现在我有:

$time ./a.out

real    0m0.438s
user    0m0.431s
sys     0m0.003s
对于
内存池
版本,以及:

$ time ./a.out

real    0m0.008s
user    0m0.006s
sys     0m0.002s
对于标准分配器版本

问题


问题仍然存在,它速度慢是正常的吗?

我从未使用过Boost的池代码,甚至没有读过它。但是我确实知道一些关于内存池的事情,我不希望您测试中的内存池比malloc更好

要理解这一点,您必须首先了解malloc和free是如何实现的(如果您还没有实现的话)。这个问题的答案似乎提供了一个很好的总结:

内存碎片对于
malloc()
free()
来说是一个难题,没有简单、快速的解决方案。但是,如果你能保证所有的分配都是相同大小的,那就容易多了:这就是内存池获胜的方式。但是你的测试没有涉及很多内存碎片,而且可能根本没有释放多少内存。所以在这个测试中,
malloc()
赢了,而池输了。要优化测试,您可以混合使用一系列删除,例如:

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

话虽如此,如果你真的想知道为什么一段特定的代码会这样执行,你应该对它进行分析。思考代码为何以特定方式运行的理论很有用,但您还必须测试您的理论。

您是否检查了汇编代码以确保测试循环没有被优化?所有这些都是通过
-O3-DNDEBUG
实现的,对吗?@Cameron thx对于技巧,我编辑了一个问题:)根据STL实现,您可能会在重新绑定代码时损失很多时间。您是否预分配池?boost::pool只使用一个空闲列表,因此除非您预先分配,否则使用malloc/new的开销完全大于使用malloc/new的开销。我会尝试通过创建一个分配列表来随机分配和释放随机大小的东西,然后随机分配,或者,如果列表不是空的,则释放列表中的随机元素。一旦开始运行分配,您将开始分割内存。
$time ./a.out

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

real    0m0.008s
user    0m0.006s
sys     0m0.002s
// Allocate 10,000 things
// Loop 10 times:
//   Allocate 1,000 things
//   Delete 1,000 things