C++ 应用程序性能优化 — 内存池

如果应用程序频繁地在堆上分配和释放内存,则会导致性能的损失。并且会使系统中出现大量的内存碎片,降低内存的利用率。

内存池可以分为单线程内存池和多线程内存池。单线程内存池整个生命周期只被一个线程使用,因而不需要考虑互斥访问的问题;多线程内存池有可能被多个线程共享,因此则需要在每次分配和释放内存时加锁。相对而言,单线程内存池性能更高,而多线程内存池适用范围更广。

MemoryBlock为内存池中附着在真正用来为内存请求分配内存的内存块头部的结构体,它描述了与之联系的内存块的使用信息:

处的作用是当内存池中已有内存块(即内存块链表不为空)时遍历该内存块链表,寻找还有”自由分配单元”的内存块。

回收分配单元时,可能会将整个内存块返回给进程堆,也可能将被回收分配单元所属的内存块移至内存池的内存块链表的头部。这两个操作都需要修改链表结构。这时需要知道该内存块在链表中前一个位置的内存块。

这时将pMyBlock的nFree递增1,表示此内存块的自由分配单元多了一个。

处将pMyBlock的nFirst值改变为指向这个待回收分配单元的编 ,其编 通过计算此单元的起始位置相对pMyBlock的aData位置的差值,然后除以步长(nUnitSize)得到。

⑤处检查当回收完毕后,包含此回收单元的内存块的所有单元是否都处于自由状态,且此内存是否处于内存块链表的头部。如果是,将此内存块整个的返回给进程堆,同时修改内存块链表结构。

另外还需注意的是,这里并不能比较nFree与nInitSize或nGrowSize的大小来判断某个内存块中所有分配单元都为自由状态,这是因为第1次分配的内存块(分配单元个数为nInitSize)可能被移到链表的后面,甚至可能在移到链表后面后,因为某个时间其所有单元都处于自由状态而被整个返回给进程堆。即在回收分配单元时,无法判定某个内存块中的分配单元个数到底是nInitSize还是nGrowSize,也就无法通过比较nFree与nInitSize或nGrowSize的大小来判断一个内存块的所有分配单元是否都为自由状态

不难发现,这时nFirst的值由原来的0变为m。即此内存块下一个被分配的单元是m编 的单元,而不是0编 的单元(最先分配的是最新回收的单元,从这一点看,这个过程与栈的原理类似,即先进后出。只不过这里的”进”意味着”回收”,而”出”则意味着”分配”)。相应地,m的”下一个自由单元”标记为0,即内存块原来的”下一个将被分配出去的单元”,这也表明最近回收的分配单元被插到了内存块的”自由分配单元链表”的头部。当然,nFree递增1。

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2014年11月26日
下一篇 2014年11月26日

相关推荐