(序)
这两三天,想了想啥都没干,竟折腾内存池了。为了设计一个简单的内存池,在网上搜了又搜,最终还是不尽人意。
关于STL内存池的介绍,网上有很多大牛对此进行了详细的阐述,精辟而且细致,令人佩服。
下面几篇是关于内存池设计思想或源码解析的一些比较好的文章:
1. http://blog.csdn.net/houapple/article/details/6492735 (STL内存池学习)
2. http://space.189works.com/home-space-uid-10212494-do-blog-id-32448.html (内存池畅想)
3. http://www.cnblogs.com/Creator/archive/2012/04/05/2433386.html (探究操作系统内存分配对齐策略)
4. http://blog.csdn.net/v_july_v/article/details/7040425 (Nginx 源码剖析之内存池)
(正文)
STL内存池主要为解决内存碎片的,对于小于等于128字节的内存申请,则利用内存池;而对于大于128字节的内存申请,则
直接利用malloc()分配。 本人最初想用内存池的主要目的,是想降低malloc() 频繁申请的时间量,然而采用内存池(STL内存池)之后,经过祖略测试
,时间是不用内存池的好几倍,尤其在多线程的时候,更是慎。Noting is perfect,然而这是否值得用内存池呢?我犹豫了.
下面是几组数据,前者是 不使用内存池的时间,后者是使用内存池的时间
(no pool)total time:0.117616
(usepool)total time:0.184892
(no pool)total time:0.121150
(usepool)total time:0.179185
(no pool)total time:0.120278
(usepool)total time:0.187158
(no pool)total time:0.117880
(usepool)total time:0.185094
(no pool)total time:0.116160
(usepool)total time:0.183146
测试代码为:
【不适用内存池的代码片段】
struct timeval no_begin,no_end; char *pno; int ran; int i; srand(17); gettimeofday(&no_begin, NULL); for(i=0;i<1000000;i++) { ran=rand()%139+1; pno=(char *)malloc(ran); free(pno); } gettimeofday(&no_end, NULL); no_total+= (no_end.tv_sec-no_begin.tv_sec)+(no_end.tv_usec-no_begin.tv_usec)*1.0/1000000;
【使用内存池的代码:把更改 malloc()为 mem_pool()即可】
...代码.略
在多线程条件下,【此时内存池要加锁,stl内存池不是线程安全的】
(no pool)total time:6.260520
(usepool)total time:79.761681(no pool)total time:6.438677
(usepool)total time:48.154732(no pool)total time:5.326588
(usepool)total time:236.397503(no pool)total time:6.157897
(usepool)total time:46.252528
可以看出,多线程条件下,使用内存池的时间开销,比不适用pool 时间慢10倍之多。测试代码具有局部性,数据统计量太小,然而这同样
能够反映问题。为什么利用内存池,时间开销增长如此大呢?
以STL内存池为例,
1. STL内存池,需要对请求字节大小,进行对齐处理(计算开销),而后还要调用真正的malloc(),,针对每一个链表,虽然只是第一
此需要调用,然而或许计算开销>malloc() 开销,并且对齐处理也浪费了一些空间
2.free()的时候,还需对 释放大小 进行对齐处理,而且这个很不人性化,人们习惯了free() 的时候,用一个指针参数就行了,谁还记
得后面的大小呢。
3 多线程条件下,需要加锁,浪费了时间,而且在malloc()中或许还有锁(线程安全的程序中,mallo() 中会有锁)