池化
首先介绍一个概念“池化技术 ”。池化技术 一言以蔽之就是:提前保存大量的资源,以备不时之需以及重复使用。
池化技术应用广泛,如内存池,线程池,连接池等等。内存池相关的内容,建议看看Apache、Nginx等开源web服务器的内存池实现。
起因:由于在实际应用当中,分配内存、创建进程、线程都会设计到一些系统调用,系统调用需要导致程序从用户态切换到内核态,是非常耗时的操作。
因此,当程序中需要频繁的进行内存申请释放,进程、线程创建销毁等操作时,通常会使用内存池、进程池、线程池技术来提升程序的性能。
线程池:线程池的原理很简单,类似于操作系统中的缓冲区的概念,它的流程如下:先启动若干数量的线程,并让这些线程都处于睡眠状态,当需要一个开辟一个线程去做具体的工作时,就会唤醒线程池中的某一个睡眠线程,
让它去做具体工作,当工作完成后,线程又处于睡眠状态,而不是将线程销毁。
进程池与线程池同理。
内存池:内存池是指程序预先从操作系统申请一块足够大内存,此后,当程序中需要申请内存的时候,不是直接向操作系统申请,而是直接从内存池中获取;
同理,当程序释放内存的时候,并不真正将内存返回给操作系统,而是返回内存池。当程序退出(或者特定时间)时,内存池才将之前申请的真正内存释放。
多级缓冲内存池也是同理,按照内存大小分配特定的内存,减少不必要的分配销毁操作。
视频请看 : http://edu.****.net/course/detail/627
1.内存池的目的
提高程序的效率
减少运行时间
避免内存碎片
2.原理
要解决上述两个问题,最好的方法就是内存池技术。具体方法就是,申请内存 :大小固定,提前申请,重复利用。
3.使用场合
长时间运行的服务程序
对速度要求高的程序
对稳定性要求高的程序
4.内存池不能满足所有的需求
内存池是不能够满足所有人的需求的,那么考虑到通用性,健壮性,需要考虑到,当申请内存块 大小不在内存池 中的情况
或者内存池中已经没有内存块了,所采取的措施:直接使用系统的申请,释放函数。
内存池的设计 :
内存池中有很多内存块,内存池中有很多链表,每一个链表中存储一种固定大小的内存块,例如128字节链表中存储的是大小都为
128字节的内存块,依次类推,内存池中维护了很多个这样的链表。
这里我们要解决的第一个问题是,当我们申请内存是,首先要找到对应大小的链表,如果设计可以避免这个查找过程。
从内存链表中申请内存过程中,不需要查找,直接返回可用内存(链表可轻松实现)
解释释放内存的时候,如何快速的把内存块放回到对应的链表中
下面针对上述问题做依次设计:
首先在数据结构上进行申请的研究:
为了能满足上面的申请,释放可以快读定位到链表,我们需要维护额外的数据结构才可以达到目标,思路如下:
在申请内存的时候需要多申请一部分作为系统使用,系统使用的内存结构中,包含了该内存块所属的内存链表指针,这样就可以
快速度的释放内存。
有了这个特殊的结构设计以后,我们就可以不通过查找定位到内存上。
看下面的图:
首先考虑我们申请内存的过程:
char* p = new char[100];
实际上我们给出的输入数据就是 100个字节的数据,如果我可以 MemeoryList* p = _listIndex[100];
这样就可以直接的定位到对应的链表了。
如何结合 CPU-cache实现更加高度的内存池呢 ?