内部碎片 外部碎片( 二 )


图2.2:选择存储记录的组的方法
实际上,Slab 也是有利也有弊 。下面介绍一下它的缺点 。
Slab 的缺点
Slab 解决了当初的内存碎片问题,但新的机制也给带来了新的问题 。这个问题就是,由于分配的是特定长度的内存,因此无法有效利用分配的内存 。例如,将100字节的数据缓存到128字节的chunk中,剩余的28字节就浪费了
对于该问题目前还没有完美的解决方案,但在文档中记载了比较有效的解决方案 。
The mostway tothe waste is to use a list of sizethat(if that's at all
)sizes ofthat theof thisofareto
store.
就是说,如果预先知道客户端发送的数据的公用大小,或者仅缓存大小相同的数据的情况下,只要使用适合数据大小的组的列表,就可以减少浪费 。但是很遗憾,现在还不能进行任何调优,只能期待以后的版本了 。但是,我们可以调节slab class的大小的差别
最佳适合与最差适合分配程序
最佳适合算法在功能上与最先适合算法类似,不同之处是,系统在分配一个内存块时,要搜索整个自由表,寻找最接近请求存储量的内存块 。这种搜索所花的时间要比最先适合算法长得多,但不存在分配大小内存块所需时间的差异 。最佳适合算法产生的内存碎片要比最先适合算法多,因为将小而不能使用的碎片放在自由表开头部分的排序趋势更为强烈 。由于这一消极因素,最佳适合算法几乎从来没有人采用过 。
最差适合算法也很少采用 。最差适合算法的功能与最佳适合算法相同,不同之处是,当分配一个内存块时,系统在整个自由表中搜索与请求存储量不匹配的内存快 。这种方法比最佳适合算法速度快,因为它产生微小而又不能使用的内存碎片的倾向较弱 。始终选择最大空闲内存块,再将其分为小内存块,这样就能提高剩余部分大得足以供系统使用的概率 。
伙伴(buddy)分配程序与本文描述的其它分配程序不同,它不能根据需要从被管理内存的开头部分创建新内存 。它有明确的共性,就是各个内存块可分可合,但不是任意的分与合 。每个块都有个朋友,或叫“伙伴”,既可与之分开,又可与之结合 。伙伴分配程序把内存块存放在比链接表更先进的数据结构中 。这些结构常常是桶型、树型和堆型的组合或变种 。一般来说,伙伴分配程序的工作方式是难以描述的,因为这种技术随所选数据结构的不同而各异 。由于有各种各样的具有已知特性的数据结构可供使用,所以伙伴分配程序得到广泛应用 。有些伙伴分配程序甚至用在源码中 。伙伴分配程序编写起来常常很复杂,其性能可能各不相同 。伙伴分配程序通常在某种程度上限制内存碎片 。
固定存储量分配程序有点像最先空闲算法 。通常有一个以上的自由表,而且更重要的是,同一自由表中的所有内存块的存储量都相同 。至少有四个指针:指向被管理内存的起点,MEND 指向被管理内存的末端,指向与 MEND 之间已用内存的末端,而 PFREE[n]则是指向任何空闲内存块的一排指针 。在开始时,PFREE 为 NULL,指针为 。当一个分配请求到来时,系统将请求的存储量增加到可用存储量之一 。然后,系统检查 PFREE[ 增大后的存储量 ] 空闲内存块 。因为PFREE[ 增大后的存储量 ] 为 NULL,一个具有该存储量加上一个管理标题的内存块就脱离 ,被更新 。
这些步骤反复进行,直至系统使一个内存块空闲为止,此时管理标题包含有该内存块的存储量 。当有一内存块空闲时,PFREE[ 相应存储量 ]通过标题的链接表插入项更新为指向该内存块,而该内存块本身则用一个指向 PFREE[ 相应存储量 ]以前内容的指针来更新,以建立一个链接表 。下一次分配请求到来时,系统将 PFREE[ 增大的请求存储量 ]链接表的第一个内存块送给系统 。没有理由搜索链接表,因为所有链接的内存块的存储量都是相同的 。