我正在使用一个内存池类,它可以重复使用已分配的内存地址,并且有一个自定义的分配器来包装这个类。以下代码片段给出了基本接口的概述。
当然,这种需求是有限的。但在以下情况下非常有用: - 为一个类指定分配器类型,该类以非常简单的方式使用该分配器(例如,避免即使建议分配更大的内存块)。 - 反复分配和释放相同大小的内存。 - 您希望使用分配器的类型非常小(例如,char、short、int等内置类型)。
理论上,实现可以利用内存池,每次需要从底层内存管理器中进行分配时,它会分配实际分配大小的倍数。彼此靠近的对象更适合任何缓存和/或预取算法。 我已经实现了这样一个内存池,并增加了一些开销来处理正确的分配、分割和释放(我们不能释放用户将传递给释放函数的每个地址。我们只需要释放之前已经分配的每个内存块的开始地址)。
我已经使用以下非常简单的代码测试了这两种情况:
您能想到一种情况,在该情况下它将提高性能吗?
编辑: 当然,它比
template<class alloc>
class memory_pool
: boost::noncopyable,
public allocator_traits<void>
{
public:
memory_pool(typename alloc::size_type alloc_size);
memory_pool(typename alloc::size_type alloc_size, alloc const&);
template<typename U> memory_pool(typename alloc::size_type alloc_size,
typename alloc::rebind<U>::other const&);
virtual ~memory_pool();
pointer allocate (); /*throw(std::bad_alloc)*/
void collect ();
void deallocate(pointer) throw(); /*noexcept*/
};
pointer allocate()
{/*
Checks if a suitable chunk of memory is available in a internal linked list.
If true, then the chunk is returned and the next chunk moves up.
Otherwise, new memory is allocated by the underlying allocator.
*/}
void deallocate(pointer)
{/*
Interprets the passed pointer as a chunk of memory and stores it in a linked list.
Please note that memory isn't actually deallocated.
*/}
void collect()
{/*
Effectively deallocates the cunks in the linked list.
This will be called at least once during destruction.
*/}
当然,这种需求是有限的。但在以下情况下非常有用: - 为一个类指定分配器类型,该类以非常简单的方式使用该分配器(例如,避免即使建议分配更大的内存块)。 - 反复分配和释放相同大小的内存。 - 您希望使用分配器的类型非常小(例如,char、short、int等内置类型)。
理论上,实现可以利用内存池,每次需要从底层内存管理器中进行分配时,它会分配实际分配大小的倍数。彼此靠近的对象更适合任何缓存和/或预取算法。 我已经实现了这样一个内存池,并增加了一些开销来处理正确的分配、分割和释放(我们不能释放用户将传递给释放函数的每个地址。我们只需要释放之前已经分配的每个内存块的开始地址)。
我已经使用以下非常简单的代码测试了这两种情况:
std::list<int, allocator<int>> list;
std::clock_t t = std::clock();
for (int i = 0; i < 1 << 16; ++i)
{
for (int j = 0; j < 1 << 16; ++j)
list.push_back(j);
list.unique();
for (int j = 0; j < 1 << 16; ++j)
list.pop_back();
}
std::cout << (std::clock() - t) / CLOCKS_PER_SEC << std::endl;
std::list
每次调用push_back
时都会调用allocactor::allocate(1, 0)
。 unique()
确保每个元素都将被访问并与下一个元素进行比较。
然而,结果令人失望。管理块分配内存池所需的最小开销大于系统可能获得的任何优势。您能想到一种情况,在该情况下它将提高性能吗?
编辑: 当然,它比
std::allocator
快得多。