内存池:是解决内存碎片的主要方法,由于new和malloc是直接从操作系统那里通过其算法申请内存,每次申请操作系统都要执行一次,所以申请效率不仅不高,而且频繁的申请与释放内存会形成大量的内存碎片。而内存池的主要思想就是在初始化时就分配一大块内存给程序,当需要内存时,就从这一大块中切给程序,当释放时,也是释放到内存池中,并没有释放给操作系统。这样会大大的减少内存碎片,因为所有的内存操作都只在这个内存池中进行。注意:只有频繁申请和释放内存时使用内存池才是较好的解决办法,如果只是少量的就不必使用内存池。
SGI中的Alloc类是我见过设计最优秀的内存池之一,其原理主要如下:
对于所有容器,STL默认都使用alloc类来对容器进行内存分配,而alloc内中有第一级和第二级内存配置方式。其中,第一级内存配置是对于内存需求大于128byte的对象,当小于128byte时,就采用第二级配置器,即内存池的方式进行分配内存。第一级的分配方式是直接以malloc函数进行分配。
内存池:SGI中内存池类似堆。首先,用一个16个成员的数组free_list来维护小内存,每个成员分别装的是内存大小为8byte-16-32-…-128byte的链表头,每个成员都维护着一个链表。对于要分配的内存字节,首先将之上调至8的倍数,然后对free_list中的成员进行匹配(有专门的函数完成),匹配成功以后,就将该成员下的节点分配给该所需的内存,然后将该节点删除,使链表头所指的内存始终处于空闲状态。当释放内存时,也是首先进行成员匹配,匹配成功以后,利用链表的头插法将内存插入到链表头前面,成为新的链表头。
默认每个成员分配20个节点,当所有节点用完以后,再次申请内存时,就调用refill()函数为free_list重新填充空间,新空间从内存池中获得,默认取20个节点的空间,得到空间以后按该数组成员所管理的字节数重新分配形成新的链表,从内存池(chunk_alloc函数完成)中取出内存分配给该成员,由于链表中的节点都已经用完,所以新分配的内存的头节点就成为链表头。若内存池中内存不够,则有多少就分配多少个节点给该成员。如果一个也分配不出来,chunk_alloc就调用malloc向自由空间(堆)申请内存到内存池中,申请的内存大小为所需内存的2倍,例如:如果申请32byte的内存20个,则malloc申请的内存为32byte*40。
在使用过程中,由于容器默认的就是alloc类进行内存分配,所以在初始化时,由于free_list中都是空的,在申请内存时,chunk_alloc就会向堆空间中申请内存,注意,所需内存是多大,那么就只分配给free_list中相应的成员内存空间形成链表结构,而其他成员仍然是空的。只有需要时才分配。
SGI 内存池
最新推荐文章于 2022-11-13 15:45:08 发布