高并发内存池

高并发内存池

内存池是一种动态内存分配与管理技术。 通常情况下,程序员习惯直接使用 new、 delete、malloc、free 等API申请分配和释放内存,这样导致的后果是:当程序长时间运行时,由于所申请 内存块的大小不定,频繁使用时会造成大量的内存碎片从而降低程序和操作系统的性能。内存池则是在真正 使用内存之前,先申请分配一大块内存(内存池)留作备用,当程序员申请内存时,从池中取出一块动态分 配,当程序员释放内存时,将释放的内存再放入池内,再次申请池可以 再取出来使用,并尽量与周边的空闲 内存块合并。若内存池不够时,则自动扩大内存池,从操作系统中申请更大的内存池。 

高并发内存池相比于普通内存池,在多核多线程环境下,解决竞争的问题,提高了内存池的性能和安全性,同时也解决了内存碎片引发发效率问题。

 

项目实现

该项目分为3个模块,来实现高并发内存池的基本功能

  1. thread cache:线程缓存。用于存放分配小于64k的内存,每个线程在申请内存是独享一个cache(STL),不需要为线程安全加锁,提高了线程池的效率。
  2. central cache:中心缓存。中心缓存只有一个,是所有线程共享的。中心项目的主要任务是向线程缓存提供缓存资源,并且定期向线程缓存回收缓存资源。当线程缓存需要额外申请空间时,向中心缓存中获取。当线程缓存的缓存资源大于它的规定最大数时,向中心缓存释放资源,避免单个线程占用过多的缓存资源,使资源分配的更加均匀。
  3. page cache:页缓存。页缓存是在中心缓存上一级的缓存,以页为单位完成内存的存储与分配。页缓存的主要工作是当中心缓存资源吃紧时,以页为单位,并分割成定长的内存碎片,分配给中心缓存。同时,页缓存会根据条件来回收中心缓存的资源,合并相邻的资源,组成更大的内存段,解决内存碎片化的问题。

关于内存资源

  • 在线程缓存中:内存资源是一个指针所指向的一段定长空间(void* list),相同空间长度的指针以链表的形式组织在一起,不同的空间长度资源用一个数组(freelist)来进行组织。空间长度通常是一个字节长度的整数倍,申请时不满对应空间长度的自动补满。
  • 在中心缓存中:内存资源是一个指针指向的若干单位页表组成的空间(span),相同大小的页表空间被以链表的形式组织起来,不同的链表存放在一个数组中(spanlist)。单位页表被分割成定长空间的内存段,以链表的形式存在,当线程缓存申请资源时,将这些内存段分配给线程缓存。
  • 在页缓存中:内存资源是一个指针指向的若干单位页表组成的空间(span),相同大小的页表空间以链表的形式链接,页表的大小为从1到128。不同大小的空间存放在一个数组中(pagelist),当程序开始运行时,页缓存向内存申请一个128页大小的内存,当需要较小长度的空间,从大空间的内存中分割。当内存归还至中心缓存,若该内存的左右内存都处于空闲状态,则合并成一个较大的内存存放在页缓存中。

 

项目流程

当一个线程需要申请内存资源时,创建线程缓存,根据它所需要的资源大小,由线程缓存分配给该线程。若该线程缓存中没有资源时,线程缓存向中心缓存中申请资源。中心缓存根据线程缓存申请的大小来分配资源:将中心缓存中的span中的分割好的资源给线程缓存。当中心缓存中的资源吃紧时,中心缓存向页缓存申请空间,页缓存将合适的若干页大小的资源进行分割并将资源给中心缓存使用。若页缓存没有资源,页缓存向系统申请规定最大空间的内存。

当线程归还使用后的内存,若线程缓存中的资源大于线程缓存容纳的最大资源时,将线程缓存中的资源归还给中心缓存。中心缓存接受到归还的资源后,若某一区域(span)资源处于空闲状态,寻找左右相邻的资源,判断是否也是空闲的,若是,则合并成一个较大的资源,归还给页缓存。当页缓存收到回收的资源时,判断该资源是否可以合并成一个更大的内存资源,若可以,合并后保存在数组的相应位置中,若不能,将回收后的资源保存在数组的相应位置。

 

源码链接

https://github.com/zy67/hahaha/tree/master/MemoryPool

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值