Chinaunix首页 | 论坛 | 博客
  • 博客访问: 860386
  • 博文数量: 82
  • 博客积分: 2283
  • 博客等级: 大尉
  • 技术积分: 2007
  • 用 户 组: 普通用户
  • 注册时间: 2012-07-15 22:19
文章分类

全部博文(82)

文章存档

2012年(82)

分类: LINUX

2012-07-27 09:49:07

     SLUB的总体思想还是跟SLAB类似,对象池里面的内存都是以“大块”为单位来进行分配与回收的。然后每个“大块”又按对象的大小被分割成“小块”,使用者对于对象的分配与回收都是以“小块”为单位来进行的。
SLUB的结构如下图:





      相比SLAB,SLUB还有一个比较有意思的特性。当创建新的对象池 时,如果发现原先已经创建的某个kmem_cache的size刚好等于或略大于新的size,则新的kmem_cache不会被创建,而是复用这个大小 差不多kmem_cache。所以kmem_cache里面还维护了一个refcount(引用计数),表示它被复用的次数。

另外,SLUB也去掉了SLAB中很有意思的一个特性,Coloring(着色)。

      什么是着色呢?
      一个内存“大块”,在按对象大小划分成“小块”的时候,可能并不是那么刚好,还会空余一些边边角角。着色就是利用这些边边角角来做文章,使得 “小块”的起始地址并不总是等于“大块”内的0地址,而是在0地址与空余大小之间浮动。这样就使得同一种类型的各个对象,其地址的低几位存在更多的变化。

      为什么要这样做呢?
      这是考虑到了CPU的cache。在学习操作系统原理的时候我们都听说过,为提高CPU对内存的访存效率,CPU提供了cache。于是 就有了从内存到cache之间的映射。当CPU指令要求访问一个内存地址的时候,CPU会先看看这个地址是否已经被缓存了。


      内存到cache的映射是怎么实现的呢?或者说CPU怎么知道某个内存地址有没有被缓存呢?
      一种极端的设计是“全相连映射”,任何内存地址都可以映射到任何的cache位置上。那么CPU拿到一个地址时,它可能被缓存的cache位置就太多了,需要维护一个庞大的映射关系表,并且花费大量的查询时间,才能确定一个地址是否被缓存。这是不太可取的。
      于是,cache的映射总是会有这样的限制,一个内存地址只可以被映射到某些个cache位置上。而一般情况下,内存地址的低几位又决定了内存被cache的位置(如:cache_location = address % cache_size)。
好了,回到SLAB的着色,着色可以使同一类型的对象其低几位地址相同的概率减小,从而使得这些对象在cache中映射冲突的概率降低。
      这有什么用呢?
      其实同一种类型的很多对象被放在一起使用的情况是很多的,比如数组、链表、vector、等等情况。当我们在遍历这些对象集合的时候,如果每一个对象都能被CPU缓存住,那么这段遍历代码的处理效率势必会得到提升。这就是着色的意义所在。

      SLUB把着色给去掉了,是因为对内存使用更加抠门了,尽可能的把边边角角减少到最小,也就干脆不要着色了。还有就是,既然kmem_cache可以被size差不多的多种对象所复用,复用得越多,着色也就越没意义了。
阅读(2025) | 评论(3) | 转发(0) |
给主人留下些什么吧!~~

Bean_lee2012-07-29 09:39:12

着色意义并不是很大,表面看,slab好像充分考虑了缓存的line的长度,实际上,收益并不大,反而增加了代码的复杂度。简单说就是着色这个feature 性价比不好

流云哭翠2012-07-27 18:51:43

zhe_wang: 研究的东西很深奥。.....
因为那本书上提到了对象复用和缓存着色......(原话:linux通过slab分配器分配task_struct结构,这样能达到对象复用和缓存着色的目的..)  查的时候又了解到现在内核已经用slub替换slab了.....所以就了解了一下~~~

zhe_wang2012-07-27 18:38:16

研究的东西很深奥。