Pool分配是一種分配內存方法,用于快速分配同樣大小的內存塊,
尤其是反復分配/釋放同樣大小的內存塊的情況。
1. pool
快速分配小塊內存,如果pool無法提供小塊內存給用戶,返回0。
Example:
void func()
{
boost::pool<> p(sizeof(int));
^^^^^^^^^^^
指定每次分配的塊的大小
for (int i = 0; i < 10000; ++i)
{
int * const t = p.malloc();
pool分配指定大小的內存塊;需要的時候,pool會向系統
申請大塊內存。
... // Do something with t; don't take the time to free() it
p.free( t );
// 釋放內存塊,交還給pool,不是返回給系統。
}
pool的析構函數會釋放所有從系統申請到的內存。
2. object_pool
與pool的區別在于:pool需要指定每次分配的塊的大小,object_pool需要指定
每次分配的對象的類型。
Example:
struct X { ... }; // has destructor with side-effects
void func()
{
boost::object_pool<X> p;
^
for (int i = 0; i < 10000; ++i)
{
X * const t = p.malloc();
注意;X的構造函數不會被調用,僅僅是分配大小為sizeof(X)
的內存塊。如果需要調用構造函數(像new一樣),應該調用
construct。比如:
X * const t = p.construct();
...
}
}
3. singleton_pool
與pool用法一樣。不同的是:可以定義多個pool類型的object,都是分配同樣
大小的內存塊;singleton_pool提供靜態成員方法分配內存,不用定義object。
Example:
struct MyPoolTag { };
typedef boost::singleton_pool<MyPoolTag, sizeof(int)> my_pool;
void func()
{
for (int i = 0; i < 10000; ++i)
{
int * const t = my_pool::malloc();
// ^^^^^^^^^
// 和pool不一樣。
...
}
my_pool::purge_memory();
// 釋放my_pool申請的內存。
}
4. pool_alloc
基于singleton_pool實現,提供allocator(用于STL等)。
Example:
void func()
{
std::vector<int, boost::pool_allocator<int> > v;
for (int i = 0; i < 10000; ++i)
v.push_back(13);
}
需要的話,必須自己顯式地調用
boost::singleton_pool<boost::pool_allocator_tag, sizeof(int)>::release_memory()
把allocator分配的內存返回系統。
實現原理
pool每次向系統申請一大塊內存,然后分成同樣大小的多個小塊,
形成鏈表連接起來。每次分配的時候,從鏈表中取出頭上一塊,提
供給用戶。鏈表為空的時候,pool繼續向系統申請大塊內存。
一個小問題:在pool的實現中,在申請到大塊內存后,馬上把它分
成小塊形成鏈表。這個過程開銷比較大。即你需要分配一小塊內存
時,卻需要生成一個大的鏈表。用如下代碼測試:
boost::pool<> mem_pool(16);
for(i = 0; i < NPASS; i++) {
period = clock();
for(n = 0; n < NITEM; n++) {
array_ptr[n] = (int *)mem_pool.malloc();
}
for(n = 0; n < NITEM; n++) {
mem_pool.free(array_ptr[n]);
}
period = clock() - period;
printf("pool<> : period = %5d ms ", period);
}
可以發現,第一遍花的時間明顯多于后面的。
而且在pool的使用過程中如果不是恰好把鏈表中所有的小塊都用上
的話,在鏈表中最后的一些小塊會始終用不上。把這些小塊加入鏈
表是多余的。雖然這個開銷可能很小:)
轉自:http://blog.csdn.net/xushiweizh/archive/2006/11/21/1400426.aspx