优先级队列中的池内存分配

时间:2011-03-08 22:06:44

标签: c++ priority-queue event-driven

我正在编写一个基于事件的模拟器,其中每个事件都调用一个可以生成新事件的处理函数(节点),依此类推。 时间戳与每个事件相关联,并且它们需要按照增加的时间顺序进行处理(但事件不一定按该顺序创建)。为此,我使用了一个简单的priority_queue<Event*>,其中Event是一个包含指向必须调用的处理节点的指针和时间戳的类。

所以,一切正常,但我每秒分配和释放数百万个事件,这显然限制了我的模拟器的速度(大约30%的执行时间是由内存分配和事件对象的释放占用的)。

我发现了这个问题: Object pool vs. dynamic allocation似乎我可以从对象池中受益匪浅。虽然我已经看到Boost提供了一些方法来做到这一点,但我不确定这是否适用于在priority_queue中实现池。在定制内存分配方面,我真的很失落。

所以我的问题是:为我的priority_queue使用对象池是否实用/有益,如果是,有一种简单的方法可以做到这一点,也许有些代码示例(或至少是一个起点),最好不要在第一时间立即依赖Boost?

实际上有些人会理解游泳池分配如何运作也是受欢迎的!

感谢。

3 个答案:

答案 0 :(得分:1)

是的,这样做非常实用。请记住,内置的动态分配器可以为每个目的尽可能快地构建 - 也就是说,它必须分配和取消分配任何大小,任何类型和任何顺序。如果您事先知道这不是必要的,那么您可以大大降低分配和解除分配的复杂性。

在这种情况下,您事先知道您总是分配一个事件。这使得对象池成为您的目的的优秀分配器。添加一个自定义分配器是非常实用的,该分配器设计用于与std::priority_queue的STL对象 - 该队列在内部容器上进行模板化,默认为std::vector,您可以明确指定std::vector中的自定义分配器。结果应该非常实用且易于使用 - 像对象池一样基于值的自定义内存分配器(据我所知)相当容易插入。

答案 1 :(得分:0)

我想你在谈论std::priority_queue。是的,可以提供自己的分配方案。

STL优先级队列是根据另一个容器(我认为是std::vector)实现的,可以指定为模板参数。然后,您可以使用分配器(以通常的STL方式)参数化其他容器。

它仍然是分配器的实现。如果您不想自己动手,我很确定您可以找到很多(例如,您提到过Boost)。我曾经使用a segregated pool implementation from here进行了一些小修改。它做得很好......

答案 2 :(得分:0)

对象池的快速而肮脏的示例

<强> EventPool.h

#include <stack>
class Event;

class EventPool
{
 public:
   explicit EventPool(const unsigned int initSize = 0);
   ~EventPool();
   Event* getEvent();
   void returnEvent(Event* e);
 private:
   std::stack<Event*> pool_;
};

<强> EventPool.cxx

#include <Event.h>
#include <EventPool.h>

EventPool::EventPool(const unsigned int initSize)
{
   for(unsigned int i = 0; i < initSize; ++i)
   {
      pool_.push(new Event());
   }
}

EventPool::~EventPool()
{
   while(!pool_.empty())
   {
      delete pool_.top();
      pool_.pop();
   }
}

Event* EventPool::getEvent()
{
   if(pool_.empty())
   {
      return new Event();
   }
   Event* returnValue = pool_.top();
   pool_.pop();
   return returnValue;
}

void EventPool::returnEventToPool(Event* e)
{
   pool_.push(e);
}

通过执行此操作,您可以允许池控制自身的大小。当另一个对象抓取一个事件时,由抓取器决定是给予事件还是删除它。