C++STL内存池

一、STL内存池机制

STL内存池机制,使用双层级配置器。第一级采用malloc、free,第二级视情况采用不同策略。具体的来说:

第一级配置器 __malloc_alloc_template 仅仅只是对 malloc 的一层封装,没有考虑可能出现的内存碎片化问题。内存碎片化问题在大量申请小块内存是可能非常严重,最终导致碎片化的空闲内存无法充分利用。

SGI 于是在第二级配置器 __default_alloc_template 中 内置了一个轻量级的内存池。 对于小内存块的申请,从内置的内存池中分配。然后维护一些空闲内存块的链表(简记为空闲链表,free list),小块内存使用完后都回收到空闲链表中,这样如果新来一个小内存块申请,如果对应的空闲链表不为空,就可以从空闲链表中分配空间给用户。

二、流程

第二级配置器目的解决小型区块造成的内存碎片问题。使用自由链表(free-list)的技巧。主动将不论什么小额区块的内存需求量上调至8的倍数。如需求30,则上调至32。具体而言SGI默认最大的小块内存大小为128bytes,并设置了128/8=16 个free list,每个list 分别维护大小为 8, 16, 24, …, 128bytes 的空间内存块(均为8的整数倍),如果用户申请的空间大小不足8的倍数,则向上取整。

free-list节点结构

  union _Obj { // 自由链表的每个node的定义
        union _Obj* _M_free_list_link;
        char _M_client_data[1];   };
  static _Obj* __STL_VOLATILE _S_free_li

 假如有16个free-lists。各自管理大小分别为8、16、24、32、40、48、56、64、72、80、88、96、104、112、120、128 bytes的小额区块。
    申请流程例如以下:

释放流程例如以下:

三、SGI STL 内存池在多线程下的互斥访问

最后,我们来看看SGI STL中如何处理多线程下对内存池互斥访问的(实际上是对相应的free list进行互斥访问,这里访问是只需要对free list进行修改的访问操作)。在SGI的第二级配置器中与内存池互斥访问相关的就是 _Lock 这个类了,它仅仅只包含一个构造函数和一个析构函数,但这两个函数足够了。在构造函数中对内存池加锁,在析构函数中对内存池解锁:

 in __default_alloc_template
# ifdef __STL_THREADS
    static _STL_mutex_lock _S_node_allocator_lock; // 互斥锁变量
# endif
class _Lock {
    public:
        _Lock() { __NODE_ALLOCATOR_LOCK; }
        ~_Lock() { __NODE_ALLOCATOR_UNLOCK; }
};
 in preprocess
#ifdef __STL_THREADS
# include <stl_threads.h> // stl 的线程,只是对linux或windows线程的一个封装
# define __NODE_ALLOCATOR_THREADS true
# ifdef __STL_SGI_THREADS
#   define __NODE_ALLOCATOR_LOCK if (threads && __us_rsthread_malloc) \
                { _S_node_allocator_lock._M_acquire_lock(); }  // 获取锁
#   define __NODE_ALLOCATOR_UNLOCK if (threads && __us_rsthread_malloc) \
                { _S_node_allocator_lock._M_release_lock(); }  // 释放锁
# else /* !__STL_SGI_THREADS */
#   define __NODE_ALLOCATOR_LOCK \
        { if (threads) _S_node_allocator_lock._M_acquire_lock(); }
#   define __NODE_ALLOCATOR_UNLOCK \
        { if (threads) _S_node_allocator_lock._M_release_lock(); }
# endif
#else /* !__STL_THREADS */
#   define __NODE_ALLOCATOR_LOCK
#   define __NODE_ALLOCATOR_UNLOCK
#   define __NODE_ALLOCATOR_THREADS false
#endif

四、内存池优缺点

    优点
    对于频繁地申请小块内存,减少了申请的时间。
    缺点
    由于自由链表的内存块大小不连续(8、16、24 …),导致了内部碎片的产生。这使得内存利用率不高。
    小块内存释放之后,并没有归还给操作系统,而是放到了自由链表中,会导致系统内存越来越少,除非到程序结束,否则内存不会归还给操作系统。
 

参考:

https://www.cnblogs.com/zsychanpin/p/6936810.html

https://blog.csdn.net/wang13342322203/article/details/99709860

https://blog.csdn.net/a987073381/article/details/52245795?utm_medium=distribute.pc_relevant.none-task-blog-OPENSEARCH-3.edu_weight&depth_1-utm_source=distribute.pc_relevant.none-task-blog-OPENSEARCH-3.edu_weight

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值