概念

内存池就是在程序启动时,预先向堆中申请一部分内存,交给一个管理对象。在程序运行中,需要时向管理对象“借”,不需要时“还”给管理对象。
原理很简单,关键是怎样才能高效地“借”、“还”。

实例场景

在C/S服务器中,需要频繁地收发数据包。而数据包的内存采用原始的new-delete模式,会大大降低服务器性能,所以想到了使用内存池技术。
在此实例中有几个硬性条件:
1、数据包最大长度可预期,所以内存池中块的大小暂且规定为1024。
2、内存池适用于多线程情况。也就是说,可以同时有多人“借”同一个空闲块。

设计思路

一、内存存放结构

二、第一次“借”
遍历内存池,发现块1空闲(可以“借”出去)。标记块1为“已借”,记录此时位置(1,1)。然后,把块1“借出去”。

三、连续几次“借”出,中途可能有几次归“还”
“借”的时候都是在上次“借”出的位置基础上往后遍历,运气差会遍历到末尾。当然,多线程嘛,中途可能有几次归还,对借出也没干扰。归还时,标记块的状态为“空闲”即可。状态为bool值,在一读一写的情况下,不需要加锁。怎么说时一读一写呢?借的时候需要加锁(一读),借出后,只可能借到的人写(一写)。

四、遍历到末尾了
在借借还还中,总会出现这种情况。当前位置(3,1),后边的块全部标记为“已借”。很明显,这样会直接遍历到末尾。后边没数据了,只有看看头部到(3,1)这部分数据块有空闲的没。很幸运的是,遍历到了(1,2)空闲。

五、没有空闲的块了
当从当前位置往后遍历,没有空闲块。然后在从头部遍历到当前位置,依然没有空闲块。说明,该添加新的内存到内存池了。然后,直接返回刚申请内存的第一块。

说点啥

这只是众多思路中的一个。有瑕疵,却想不出更好的办法。麻烦的就是需要考虑多线程,有多线程就得加锁,加锁就是变相的单线程,就会影响效率。这里我只给借内存加了锁,还内存可以不加锁。先尝试这多写几个实例出来,比比哪种方法更高效。

代码

这里采用模版类,通用性更强。编译通过了,但没有使用过。

template<class T>
struct sBlock
{T       t;      //放在头部,方便指针强转换char    flag;   //可用标志, 0:可用 1:不可用
};
#ifndef MEMPOOL_H
#define MEMPOOL_H#include <vector>
#include <mutex>
using namespace std;template<class T>
class MemPool
{
public:MemPool(): m_curBuffIndex(0), m_curBlockIndex(0), m_baseBuffCount(0), m_baseBlockCount(0){}~MemPool() {}bool init(unsigned int buffCount, unsigned int blockCount){m_baseBuffCount = buffCount;m_baseBlockCount = blockCount;addBuff();return true;}T* mallocT(){lock_guard<mutex> lk(m_mt);//遍历后方for ( ; m_curBuffIndex < m_buffs.size(); ++m_curBuffIndex){for ( ; m_curBlockIndex < m_baseBlockCount; ++m_curBlockIndex){if (m_buffs[m_curBuffIndex][m_curBlockIndex].flag == 0){m_buffs[m_curBuffIndex][m_curBlockIndex].flag = 1;return m_buffs[m_curBuffIndex][m_curBlockIndex];}}m_curBlockIndex = 0;}//遍历前方int tempIndex = m_curBuffIndex;for (m_curBuffIndex = 0; m_curBuffIndex < tempIndex; ++m_curBuffIndex){for (; m_curBlockIndex < m_baseBlockCount; ++m_curBlockIndex){if (m_buffs[m_curBuffIndex][m_curBlockIndex].flag == 0){m_buffs[m_curBuffIndex][m_curBlockIndex].flag = 1;return m_buffs[m_curBuffIndex][m_curBlockIndex];}}m_curBlockIndex = 0;}//没有空闲的内存块,申请新内存int tempSize = m_buffs.size();addBuff();m_curBuffIndex = tempSize;m_buffs[m_curBuffIndex][m_curBlockIndex].flag = 1;return m_buffs[m_curBuffIndex][m_curBlockIndex];}void freeT(T* p){memset(p, 0, sizeof(T));sBlock<T>* pbk = (sBlock<T>*)p;pbk->flag = 0;      //原子操作,一读一写,不需要加锁}private:void addBuff(){for (int i = 0; i < m_baseBuffCount; i++){int size = sizeof(sBlock<T>) * m_baseBlockCount;sBlock<T>* pBlocks = (sBlock<T>*)malloc(size);memset(pBlocks, 0, size);m_buffs.push_back(pBlocks);}}private:vector<sBlock<T>*>  m_buffs;unsigned int        m_curBuffIndex;     //当前正在使用的大内存索引unsigned int        m_curBlockIndex;    //当前正在使用的块索引unsigned int        m_baseBuffCount;    //大内存基数量,每次新增大内存数unsigned int        m_baseBlockCount;   //每一个大内存包含多少个块mutex               m_mt;
};#endif // MEMPOOL_H

内存池简单实现(一)相关推荐

  1. 内存池 - 原理分析(一)

    这里写目录标题 思考 什么是内存池? 内存池作用 内存池的演变 版本一 版本二 总结 后续 思考 什么是内存池?内存池是做什么的?核心是什么?(心想这不是废话吗!肯定时管理内存的,具体呢). 内存池这 ...

  2. C++11实现高效内存池

    C++11实现高效内存池 前言 项目介绍 内存池是什么 allocator详解 MemoryPool.tcc allocateBlock 创建Block块 padPointer 空间对齐 Memory ...

  3. (转载)简单linux C++内存池

    C++代码 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 ...

  4. C++简单实现GC和内存池

    C++简单实现GC和内存池 本章前言: 这章就是为了避开传统的new\delete创建堆对象的手法,如果使用不当指针容易出现问题,所以本章简单的实现了引用计数垃圾回收,使用起来貌似还不错.Bug还有待 ...

  5. 源码分享:C++矩阵类CLMatrixT,功能强大使用简单,支持内存池、宽指令、并行化加速!持续更新...

    CLMatrixT文档目录: C++矩阵类模板CLMatrixT介绍: 特点 新增功能 先演示使用方法: 再看运行测试结果: 最后分享源代码: C++矩阵类模板CLMatrixT介绍: 最近在研究AI ...

  6. 实现自己的operator new和operator delete以及实现一个简单的内存池管理类

    为什么有必要写自己的operator new和operator delete? 为了效率.缺省的operator new和operator delete具有非常好的通用性,它的这种灵活性也使得在某些特 ...

  7. 用模版实现简单的内存池

    程序中有时候会遇到这种情况,就是需要不停的去分配以及释放内存.带来的是不停的调用new以及delete带来的开销. 而且由于全局的new以及delete往往对多线程做出了并发保护,所以在单线程情况下这 ...

  8. C++ 实现一个简单内存池

    在使用内存池进行内存管理之前,通常使用new/malloc或者delete/free来申请或者释放内存.在这个过程中,系统要首先查找内部维护的内存空闲块表,并且需要根据比如LRU等内存分配算法找到合适 ...

  9. C++内存池的简单原理及实现

    为什么要用内存池 C++程序默认的内存管理(new,delete,malloc,free)会频繁地在堆上分配和释放内存,导致性能的损失,产生大量的内存碎片,降低内存的利用率.默认的内存管理因为被设计的 ...

最新文章

  1. 一次性理清JavaScript变量等高难度面试问题
  2. 用Java实现Stream流处理中的滑窗
  3. opensuse11.4 apache2 403 错误.
  4. SAP Spartacus outlet.directive.ts里this.templateRef的来源
  5. python构建二叉树_BinaryTree:学习二叉树的Python库
  6. excel表格不够怎么添加_这个Excel表格,怎么做的这么漂亮
  7. 【每日SQL打卡】​​​​​​​​​​​​​​​DAY 12丨游戏玩法分析 V【难度困难】
  8. linux samba安装配置 总结
  9. 软件测试入坑建议:新手零基础怎么入门软件测试?你还缺这几份资料!
  10. winform 获取当前项目所在的路径
  11. Layui 表格table自定义每一列的样式
  12. JDK的Proxy技术实现AOP,InvocationHandler和Proxy详解——Spring AOP(三)
  13. 革命!安装杜比声卡驱动
  14. Java概述、Jdk的安装、关键字
  15. 友盟 android版本统计,友盟统计下载_友盟统计安卓版下载_友盟统计手机版下载_友盟统计app_易玩网...
  16. android本地视频 投屏,小米投屏神器
  17. 已解决Python爬虫网页中文乱码问题
  18. Linux下安装sublime汉化版及完美输入中文
  19. 开源生物特征识别库 OpenBR
  20. python网络爬虫(第八章:图像识别与文字处理)

热门文章

  1. 应用白名单:方法与挑战
  2. 春天的马车曲(横光利一)
  3. win7下ie6兼容测试之Windows7(win7)下 XP Mode 下载、安装、设置完全图解
  4. 68013上电“unknown device
  5. LSP 语言服务协议
  6. 雄关漫道真如铁,而今迈步从头越
  7. C++继承继承知识点
  8. micro-F1和macro-F1评价指标的理解
  9. Ehcache缓存时间设置
  10. google检索技巧-从菜鸟到黑客