首页 > 系统相关 > 3.什么是内存池,如何实现

3.什么是内存池,如何实现

时间:2023-08-02 21:56:23浏览次数:33  
标签:20 实现 申请 如何 内存 operator new 区块

3.什么是内存池,如何实现

内存池(Memory Pool) 是一种内存分配方式。通常我们习惯直接使用new、malloc 等申请内存,这样做的缺点在于:由于所申请内存块的大小不定,当频繁使用时会造成大量的内存碎片并进而降低性能。内存池则是在真正使用内存之前,先申请分配一定数量的、大小相等(一般情况下)的内存块留作备用。当有新的内存需求时,就从内存池中分出一部分内存块, 若内存块不够再继续申请新的内存。这样做的一个显著优点是尽量避免了内存碎片,使得内存分配效率得到提升。

这里简单描述一下《STL源码剖析》中的内存池实现机制

allocate 包装 malloc,deallocate包装free

一般是一次20*2个的申请,先用一半,留着一半,为什么也没个说法,侯捷在STL那边书里说好像是C++委员会成员认为20是个比较好的数字,既不大也不小。

  1. 首先客户端会调用malloc()配置一定数量的区块(固定大小的内存块,通常为8的倍数),假设40个32bytes的区块,其中20个区块(一半)给程序实际使用,1个区块交出,另外19个处于维护状态。剩余20个(一半)留给内存池,此时一共有(20*32byte)
  2. 客户端之后有有内存需求,想申请(20*64bytes)的空间,这时内存池只有(20*32bytes),就先将(10*64bytes)个区块返回,1个区块交出,另外9个处于维护状态,此时内存池空空如也.
  3. 接下来如果客户端还有内存需求,就必须再调用malloc()配置空间,此时新申请的区块数量会增加一个随着配置次数越来越大的附加量,同样一半提供程序使用,另一半留给内存池。申请内存的时候用永远是先看内存池有无剩余,有的话就用上,然后挂在0-15号某一条链表上,要不然就重新申请。
  4. 如果整个堆的空间都不够了,就会在原先已经分配区块中寻找能满足当前需求的区块数量,能满足就返回,不能满足就向客户端报bad_alloc异常

allocator就是用来分配内存的,最重要的两个函数是allocate和deallocate,就是用来申请内存和回收内存的,外部(一般指容器)调用的时候只需要知道这些就够了。

内部实现,目前的所有编译器都是直接调用的::operator new()和::operator delete(),说白了就是和直接使用new运算符的效果是一样的,所以老师说它们都没做任何特殊处理。

其实最开始GC2.9之前

new和 operator new 的区别:new 是个运算符,编辑器会调用 operator new(0)

operator new()里面有调用malloc的操作,那同样的 operator delete()里面有调用的free的操作

GC2.9下的alloc函数的一个比较好的分配器的实现规则如下:

维护一条0-15号的一共16条链表,其中 0 号表示8 bytes ,1 号表示 16 bytes,2 号表示 24 bytes。。。。而15 号表示 16* 8 = 128 bytes。

如果在申请内存时,申请内存的大小并不是8的倍数(比如2、4、7、9、18这样不是8的倍数),那就找刚好能满足内存大小的链表。比如想申请 12 个大小,那就按照 16 来处理,也就是找 1 号链表了;想申请 20 ,距离它最近的就是 24 了,那就找 2 号链表。

只许比所要申请的内容大,不许小!

但是现在GC4.9及其之后 也还有 alloc 函数,只不过已经变成_pool_alloc这个名字了,名字已经改了,也不再是默认的了。

你需要自己手动去指定它可以自己指定,比如

vector<string,__gnu_cxx::pool_alloc<string>> vec;

标签:20,实现,申请,如何,内存,operator,new,区块
From: https://www.cnblogs.com/codemagiciant/p/17601854.html

相关文章

  • 4.可以说一下你了解的C++得内存管理吗?
    4.可以说一下你了解的C++得内存管理吗?1.一个由c/C++编译的程序占用的内存分为以下几个部分:C++中的内存分区,分别是堆、栈、自由存储区、全局/静态存储区、常量存储区和代码区。如下图所示栈:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自......
  • jvm attach过程与底层实现
    rasp的技术重点之一是java-agent技术,通过agent可以获取到Instrumentation接口的实现,通过这个inst变量对字节码进行修改。javaagent可以在jvm启动时使用-agentjar参数启动,也可以在运行时通过attach相应进程,并且指明需要加载的jar包,就可以进入到jar包中定义好的agentmain方法处,执......
  • 5.C++中类的数据成员和成员函数内存分布情况
    5.C++中类的数据成员和成员函数内存分布情况非静态成员的数据类型大小之和。编译器加入的额外成员变量(如指向虚函数表的指针)。为了边缘对齐优化加入的padding。空类(无非静态数据成员)的对象的size为1,当作为基类时,size为0。C++类是由结构体发展得来的,所以他们的成员变......
  • 128.用C语言实现C++的继承
    128.用C语言实现C++的继承#include<iostream>usingnamespacestd;//C++中的继承与多态structA{virtualvoidfun()//C++中的多态:通过虚函数实现{cout<<"A:fun()"<<endl;}inta;};structB:publicA//C++中的继承:B类公有继......
  • 基于蜉蝣优化算法实现聚类附matlab代码
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......
  • 如何为你的 js 项目添加 ts 支持?
    前一段时间为公司内的一个JS公共库,增加了一些TypeScript类型支持。在这里简答记录一下。安装TypeScript依赖首先安装TypeScript依赖,我们要通过tsc指令创建声明文件:pnpminstall-Dtypescript创建配置文件接下来创建TypeScript配置文件:npxtsc--init这一......
  • 公共字段自动填充_问题分析和实现思路
       ......
  • 采用PCA算法&KMeans算法来实现用户对物品类别的喜好细分(菜篮子分析)(附带数据集下载)
    实现该项目的流程如下"""项目:用户对物品类别的喜好细分(菜篮子分析)主算法:PCA降维算法KMeans算法总思路1、导包2、获取数据3、数据处理5、特征工程(使用PCA降维)6、使用KMeans算法进行模型训练7、模型评估""" Firstofall!!导包......
  • zt,UPF与低功耗设计实现实例 -- 附UPF与DC综合脚本
    https://blog.csdn.net/hungtaowu/article/details/120703931UPF与低功耗设计实现实例--附UPF与DC综合脚本sunvally已于 2022-11-1517:40:44 修改6059 收藏 98分类专栏: 低功耗设计与验证 文章标签: 硬件工程版权低功耗设计与验证专栏收录该内容29......
  • SVN地址发生改变,在小乌龟tortoiseSVN如何操作
    https://blog.csdn.net/cxltsui/article/details/106709848因为服务器更改等各种原因,SVN地址的域名发生变化,或地址发生改变,如何无需重新检出checkout就可以继续沿用原来本地代码?1.右键——TortoiseSVN——Relocate(中文版是【重新定位】)如果右击没有出现relocate可能目录层次太深......