2010-06-01 47 views
3

假设我需要经常(任意大小)分配和删除堆上的对象,如果不是删除这些对象,而是将它返回给某个“池”以便稍后重用,是否有任何性能优势?回收释放对象

它会减少堆分配/释放吗?或者它会比内存分配器性能更慢,因为“池”需要管理动态指针集合。我的用例:假设我创建了一个基于链表的队列容器,并且该表中的每个节点都分配在堆上,所以每次调用push()和pop()将分配和释放该节点:

`

template <typename T> struct QueueNode { 
    QueueNode<T>* next; 
    T object; 
} 

template <typename T> class Queue { 
    void push(T object) { 
     QueueNode<T>* newNode = QueueNodePool<T>::get(); //get recycled node 
     if(!newNode) { 
      newNode = new QueueNode<T>(object); 
     } 
     // push newNode routine here.. 
    } 
    T pop() { 
     //pop routine here... 
     QueueNodePool<T>::store(unusedNode); //recycle node 
     return unusedNode->object; 
    } 
} 

`

+0

我的另一个问题是想我需要使用队列或列表,然后每次来管理回收点你调用push(),你实际上在池中做了pop(),并且push()来排队,这将会是更长的两倍,是明智的吗? – uray 2010-06-01 21:48:23

回答

1

我有类似的担忧,当我问this question.的答案可能是有见地的你,特别是那些解决内存碎片的关注。

0

这是一个特别有用的工具,使内存分配更具确定性。如果预先分配了从中生成池的大块,它还可以减少内存碎片。

0

根据您的运行时库,您可能在很多情况下具有“足够好”的分配器。也就是说,如果你能证明你有一个特殊的用例,或者libc中malloc的实现不好,你应该只为你的应用程序构建一个池分配器。

由于Doug Lea的大部分工作都存在于GNU库中,因此您可能想了解他在A Memory Allocator中的经验。

+0

我上次检查时,glibc自带的默认分配器已经为小对象实现了空闲列表(又名池)(如果我没有记错的话,最多可以有16个字节,或者是64吗?)。 – 2010-06-01 22:12:10

+0

@Emile,多谢了一点信息。我猜自定义池的最大理由是*不知道您的目标客户将使用哪种libc。 – 2010-06-01 22:15:19