内存管理

端午在家看了一下apache的内存池,具体的实现现在也想不起来了,涌上心头的是,为什么要实现这么一个内存池?简单的malloc有什么错呢?这篇文章把很多问题都解答了:

http://rdc.taobao.com/blog/cs/wp-content/plugins/glibc%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86ptmalloc%E6%BA%90%E4%BB%A3%E7%A0%81%E5%88%86%E6%9E%904.pdf(glibc源代码分析)

目前比较赞同的一点是,过多的malloc,后面确实会忘记free,又或者在所有的地方free太麻烦了。然后文中的经验教训有两个:

第一,后分配的先释放。堆是由低往高生长的,只有高于正常部分的内存才会被回收,并且,高出的那部分要连续大小达到一个阀值才会被回收,类似于,大于100,并且从100到120是空闲的,那么20会被回收,但是如果到达了150,但是130到140之间的10还被使用,那100到150之间空间的30不会被回收。(具体数值参见设定的阀值规则,这里仅是举例)采取后分配先释放则不会产生这样的问题。

第二,要自己管理,那就全部自己管理。文中对小于64kb的内存请求从自己的cache中取,而大于64kb的则直接malloc,导致内存碎片。

有空得看一下TcMalloc。

=================================

今天看了一下《stl源码剖析》的内存管理部分,简要记录一下SGI的内存管理策略。

首先,大于128字节的分配请求会直接使用malloc,这没什么好说的(当然里面如何和c++本身的语法相联系也是可以看一下的,简要来说就是实现要求实现的接口罢了),一个注意的地方是在这里可以设置自己的out of memory hanlder,后面二级空间分配器可能会用到。

然后,小于128字节的请求由二级空间分配器管理,实际上就是一个内存池。实现上该内存池维护了16个链表,每个链表由相同大小的内存块组成,内存大小从8到128字节。主要的结构是:

union obj { //free-lists

    union obj * free_list_link;

    char client_data[1]; /* The client sees this. */

};

static obj * volatilefree_list[__NFREELISTS];

分配或释放不过是指针移动而已。最大的问题是为什么是16条链表,为什么是128字节,为什么为空链表分配内存时分配20个内存块,唯一能想到的就是——他们测试过了。

内存分配时首先将分配大小向上取整为链表空间大小,然后取对就链表的头节点即可。当链表为空时会调用malloc一次分配20+n个内存块(n怎么定没仔细看),其中一个返回给客户。当malloc不成功,则调用一级空间分配器,毕竟就算它失败,它也有out of memory handler。

内存释放则直接放回内存池,我可没看到内存池将内存返回给系统的操作!

你可能感兴趣的:(内存管理)