SGI STL的内存池

tl中各种容器都有一个可选的模板参数:allocator,也就是一个负责内存分配的组件。STL标准规定的allcator
被定义在memory文件中。STL标准规定的allocator只是单纯地封装operator new,效率上有点过意不去。

SGI实现的STL里,所有的容器都使用SGI自己定义的allocator。这个allocator实现了一个small object的内存池。
Loki里为了处理小对象的内存分配,也实现了类似的内存管理机制。

该内存池大致上,就是一大块一大块地从系统获取内存,然后将其分成很多小块以链表的形式链接起来。其内部
有很多不同类型的链表,不同的链表维护不同大小的内存块。每一次客户端要求分配内存时,allcator就根据请求
的大小找到相应的链表(最接近的尺寸),然后从链表里取出内存。当客户端归还内存时,allocator就将这块内存
放回到对应的链表里。

我简单地画了幅图表示整个结构:

allocator

allocator内部维护一个链表数组,数组元素全部是链表头指针。链表A每一个节点维护一个8bytes的内存块,链表
B每一个节点维护一个16bytes的内存块。

当客户端请求分配10bytes的内存时,allocator将10调整为最接近的16bytes(只能大于10bytes),然后发现16bytes
这个链表(链表B)里有可用内存块,于是从B里取出一块内存返回。当客户端归还时,allocator找到对应的链表,将
内存重新放回链表B即可。

大致过程就这么简单,也许有人要说用链表维护一块内存,链表本身就会浪费一些内存(在我很早前接触内存池时,
总会看到类似的论点= =|),其实通过一些简单的技巧是完全可以避免的。例如,这里allocator维护了很多内存块,
反正这些内存本身就是闲置的,因此我们就可以直接在这些内存里记录链表的信息(下一个元素)。

还是写点代码详细说下这个小技巧:

   

struct  Obj
    
{
        Obj 
*next;
    }


    
void   * mem  =  malloc(  100  );
    Obj 
* header  =  (Obj * ) mem;
    Obj 
* cur_obj  =  header;
    Obj 
* next_obj  =  cur_obj;
    
for int  i  =   0 ; ;  ++  i )
    
{
        cur_obj 
= next_obj;
        next_obj 
= (Obj*)((char*)next_obj + 10 );
        
if( i == 9 )
        
{
            cur_obj
->next = 0;
            
break;
        }

        
else
        
{
            cur_obj
->next = next_obj;
        }

    }

    free( mem );

 

这样,通过header指针和next域,就可以逐块(这里是10byts)地访问mem所指向的内存,而这些链表的节点,都
是直接保存在这块内存里的,所以完全没有额外消耗。

我用C模仿着SGI的这个allocator写了个可配置的内存池,在其上按照STL的标准包装了一个allocator,可以直接
用于VC自带的STL里。
测试代码稍微测试了下,发现在不同的机器上有明显的差距。

原文地址:http://www.cppblog.com/kevinlynx/archive/2008/06/12/53054.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值