我正在使用boost.pool,但我不知道何时使用boost::pool<>::malloc和boost::pool<>::ordered_malloc?
所以,
什么是boost::pool<>::malloc和boost::pool<>::ordered_malloc?的区别?
我应该什么时候使用boost::pool<>::ordered_malloc?
jfl*_*fly 22
首先,我们应该知道Boost Pool库背后的基本思想:simple_segregated_storage它类似于单链表,负责将内存块划分为固定大小的块:
内存池保留一个空闲的内存块列表.所以我们提到了块和块:内存池使用new或malloc分配内存块并将其划分为许多具有相同大小的内存块.
假设地址由8,4个字节对齐以存储下一个块的地址,因此存储块(8个字节*32个块)如下(存储器地址仅用于说明问题,而不是真实的):

现在,假设用户分配8个字节的内存两次,因此使用了块:[0xDD00,0xDD08),[0xDD08,0xDD10].过了一会儿,用户在[0xDD00,0xDD08)释放内存,所以这个块将返回到空闲列表.块现在是这样的:

然后用户在[0xDD08,0xDD10]释放内存,将此块放回列表中的最简单方法是更新first指向它的时间复杂度.在simple_segregated_storage<T>::free()精确地这样做:
void free BOOST_PREVENT_MACRO_SUBSTITUTION(void * const chunk)
{ //! Free a chunk.
//! \pre chunk was previously returned from a malloc() referring to the same free list.
//! \post !empty()
BOOST_POOL_VALIDATE_INTERNALS
nextof(chunk) = first;
first = chunk;
BOOST_POOL_VALIDATE_INTERNALS
}
Run Code Online (Sandbox Code Playgroud)
之后,列表将是这样的:

现在我们注意到在这些操作之后,块的列表没有按其地址排序!
如果我们想在取消分配时保留顺序,则调用pool<>::ordered_free()而不是按照pool<>::free()正确的顺序将内存放回列表中.现在我们已经知道什么是在内存池的顺序,让我们深入的源代码boost::pool<>::malloc和boost::pool<>::ordered_malloc:
void * malloc BOOST_PREVENT_MACRO_SUBSTITUTION()
{
if (!store().empty())
return (store().malloc)();
return malloc_need_resize();
}
void * ordered_malloc()
{
if (!store().empty())
return (store().malloc)();
return ordered_malloc_need_resize();
}
Run Code Online (Sandbox Code Playgroud)
我们可以看到,只有当内存块列表中没有空闲块时,它们才有所不同.在这种情况下,它分配一个新的内存块,将其空闲列表合并到池的空闲列表中,这两种方法之间的区别在于boost::pool<>::ordered_malloc在合并空闲列表时保留顺序.
以上是问题1.
那么,为什么订单很重要?!内存池似乎与无序块完美配合!
首先,如果我们想要找到n个块的连续序列,则有序的空闲列表将使其更容易.其次,让我们看一下派生类boost::pool:boost::object_pool它在破坏object_pool对象时提供非解除分配对象的自动销毁,同时你也可以手动销毁对象,例如:
class X { … };
void func()
{
boost::object_pool<X> alloc;
X* obj1 = alloc.construct();
X* obj2 = alloc.construct();
alloc.destroy(obj2);
}
Run Code Online (Sandbox Code Playgroud)
上面的代码没问题,没有内存泄漏或双重删除!这boost::object_pool怎么神奇?让我们找到析构函数的实现boost::object_pool(我的机器上有1.48的提升):
template <typename T, typename UserAllocator>
object_pool<T, UserAllocator>::~object_pool()
{
#ifndef BOOST_POOL_VALGRIND
// handle trivial case of invalid list.
if (!this->list.valid())
return;
details::PODptr<size_type> iter = this->list;
details::PODptr<size_type> next = iter;
// Start 'freed_iter' at beginning of free list
void * freed_iter = this->first;
const size_type partition_size = this->alloc_size();
do
{
// increment next
next = next.next();
// delete all contained objects that aren't freed.
// Iterate 'i' through all chunks in the memory block.
for (char * i = iter.begin(); i != iter.end(); i += partition_size)
{
// If this chunk is free,
if (i == freed_iter)
{
// Increment freed_iter to point to next in free list.
freed_iter = nextof(freed_iter);
// Continue searching chunks in the memory block.
continue;
}
// This chunk is not free (allocated), so call its destructor,
static_cast<T *>(static_cast<void *>(i))->~T();
// and continue searching chunks in the memory block.
}
// free storage.
(UserAllocator::free)(iter.begin());
// increment iter.
iter = next;
} while (iter.valid());
// Make the block list empty so that the inherited destructor doesn't try to
// free it again.
this->list.invalidate();
#else
// destruct all used elements:
for(std::set<void*>::iterator pos = this->used_list.begin(); pos != this->used_list.end(); ++pos)
{
static_cast<T*>(*pos)->~T();
}
// base class will actually free the memory...
#endif
}
Run Code Online (Sandbox Code Playgroud)
它遍历内存块列表中的所有块(list,数据成员boost::pool<>,保存从系统分配的所有内存块的位置和大小),以查找其中的任何块是否也显示在空闲列表中,如果没有,调用对象的析构函数,然后释放内存.所以它有两种交集方式,就像std :: set_intersection()一样!如果对列表进行排序,那么这样做会快得多.其实在boost::object_pool<>,订单需要,公众的成员函数:boost::object_pool<>::malloc()和boost::object_pool<>::free()刚才所说的boost::pool<>::ordered_malloc()和boost::pool<>::ordered_free()分别为:
element_type * malloc BOOST_PREVENT_MACRO_SUBSTITUTION()
{ //! Allocates memory that can hold one object of type ElementType.
//!
//! If out of memory, returns 0.
//!
//! Amortized O(1).
return static_cast<element_type *>(store().ordered_malloc());
}
void free BOOST_PREVENT_MACRO_SUBSTITUTION(element_type * const chunk)
{ //! De-Allocates memory that holds a chunk of type ElementType.
//!
//! Note that p may not be 0.\n
//!
//! Note that the destructor for p is not called. O(N).
store().ordered_free(chunk);
}
Run Code Online (Sandbox Code Playgroud)
所以对于任务2:你不需要boost::pool<>::ordered_malloc在大多数情况下使用.
| 归档时间: |
|
| 查看次数: |
2056 次 |
| 最近记录: |