ART学习笔记 Rosalloc alloc部分

Rosalloc就是google版本的Dlmalloc,负责连续地址的分配。

分配策略和dlmalloc类似,也是分箱制,至于传言中的比dlmalloc效率高支持多核我是没看出来。

不过代码倒是比dlmalloc写的较人能看懂了点。

--------------------------------------

免责声明:            |

以下内容仅供参考       |

--------------------------------------

Rosalloc将内存空间分为34个箱子等级,0~31号箱子大小为16*(箱号+1),32号箱子为1K,33号箱子为2K。

小箱子的集合就叫做Run,Run可以有多个箱子,并在头部保存了自身的状态,如bitmap来标记分配出去的内存,当前是几号箱的集合等。

Run的内存分布大概是这样的:

----Run

-------Head

-------箱子0

-------箱子1

------ 。。。。。

 

 

 

Rosalloc对每个Run的实际内存大小也是有限制的,0~7号箱子为1个page,8~15为4个page,17~31为8个page,32为16page,33为32个page,所以,实际每个Run能够拥有的箱子数量也是给定的,为Run的拥有的page大小-头部大小 /每个箱子所需要的内存 并向下取整。

所以,其实可以看到,Run的本质就是N个page,对page的具象化。

 

 

 

那么如何分配内存?

假设我需要new一个字符串,需要的内存大小为25个字节。

首先,25个字节对应的箱号就是25/16向上取整 =2 ,那么需要1号箱子。

于是找到拥有一号箱子的Run们当中的一个(其实就是保存的上次成功分配的Run),尝试从这个Run中分配。

那么如何找到free的箱子供我使用呢? Run使用了bitmap的方法来保存箱子的占用情况(上次邮件里说的marksweep算法里的位图是一个意思),找到第一个为0的bit,并以此求出该箱子的index(总体偏移量*8+第几个bit),就可以得到slot的地址了,等于Run的首地址+head的大小+每个箱子的内存大小(此处为32)*箱子的index。

 

 

上面的是最顺利的情况,一下子就分配出来了,那么运气不好的时候,比如当前Run满了呢?(这里还有个尝试是将Gc中标记为垃圾的bitmap做合并再尝试分配,比较简单就不说了。)

我们需要重新找个Run,上面有提到,Run实际就是page的具象化,那么最简单的就是我们找个free的page强制转换下再给这个page按照Run初始化下就好了。

Rosalloc中保存了free的pages,叫做FreePageRuns,遍历他,找到满足我们需要的大小的page,当前是1号箱子,也就是需要1个page。

如果找到了这样的pages(大小大于等于当前需求的),本着不能浪费的原则,将多出来的一块还给FreePageRuns,剩余的就强制转换为Run,并根据当前的箱子类型进行赋值。

     这样从一个完全free的Run中重新去尝试分配箱子是不可能失败的。

 

那么如果还没有找到呢?也就是说当前的Rosalloc管理的空间里已经找不到一个Free的page了,那么我们需要扩大,现在默认是扩大(实际需求~2M)大小的空间,并把扩大得到的内存加入FreePageRuns中管理(要么把之前最后一个free但是不够的page扩容,要么就将新的直接挂到FreePageRuns中),然后再尝试分配Run,继续上面的过程,这个也不会失败。

 

大点内存的分配和小内存的差不太多,大家看看代码就明白了。

 

总的来看,Rosalloc中的分配就三个 分配page-----分配Run----分配箱子。

 

Run够,就分配箱子。

Run满,就分配Run。

Page不够用,就分配page。

再不够就OOM挂掉。

 

 

 

你可能感兴趣的:(android)