标签:
描述将要用来分配的地址空间(逻辑地址空间,下同)。
相同大小的slot的集合。
内存分配单位。
对于run的大小可分为34个标准(bracketSizes):标号0-31的,大小为16*(i+1)个字节,其中i为标号值,32大小为1kB,33为2kB。
不同标号的run所用page数目也不一样(numOfPages):0-3 的run大小为1 page,4-7的为2 page,8-15的为4 page,16-31的为8 page,32的16 page, 33的32 page。
每个run中slot的个数可以计算出。
· Initialize
初始化bracketSizes,numOfPages等等。
· 其他
初始化free_page_runs_,第一个free page run的地址通过够在函数得到,为rosalloc space的地址,大小为capacity_。
初始化其他成员变量。
· AllocLargeObject
如果所需分配字节数超过kLargeSizeThreshold(2048),则分配大对象。大对象内存直接通过alloc pages获得。
· AllocFromRun
如果需要分配的长度小于192字节(级别11以下),从thread local中分配。如果超过这个值,调用AllocFromCurrentRunUnlocked函数,从共用中分配。
current_runs_存放了各个编号的当前可用来分配的run。Alloc函数首先从current_runs_得到即将用于分配的run,分配该run中的一个slot。Run中slot是通过bitmap管理,分配的时候通过bitmap计算得到空闲slot的地址,bitmap标记后返回该slot地址。如果在current run中分配失败,说明该run已满,需要调用RefillRun重新获得一个run,并将新的run记录为current run,然后重新分配slot。
· RefillRun
non_full_runs_中存放了既没有全部使用完,也不是current的run。Refill run的时候优先从non_full_runs_中获得,如果non_full_runs_没有该编号的run,就通过AllocRun获得一个全新的run。
· AllocRun
该函数主要做两件事:1、通过AllocPages获得一定数目的page(page数目根据编号确定);
2、对分出来的run进行初始化。如果alloc pages失败,返回Null。
· AllocPages
free_page_runs_存放了用于分配page的空间。Alloc page函数从free_page_runs_头开始查找,寻找大于所需求大小的free page run。查找结果可能两种:1、找到合适的free page run,则分割该free page run,并将剩余的作为新的free page run插入free_page_runs_;2、找不到合适的,则在原有的free_page_runs_后面扩展新的free page run结构,使满足所需求的page。扩展前会预先检查确保扩展后不会突破capacity_,扩展的大小最少为2M。扩招再进行分割,满足需求后将剩余的作为新的free page run放入free_page_runs_中去。得到符合要求的pages后,会在page_map_中标注该段pages的用途(详细看代码)。
i.
ii.
· FreeInternal
根据需要free的ptr,对比page_map_知道该段内存的用途,作为largeObject还是run。如果是largeObject,调用FreePages释放pages;如果是run,调用run的free流程FreeFromRun(run的定位通过page_map_和base计算得到)
· FreeFromRun
首先调用FreeSlot,对该run中对应的slot清0,清bitmap。
如果归还该run已经空了,没有slot被占用,则从non_full_runs_摘除该run,然后清除该run的header,调用FreePages归还pages。如果该run不为空,说明还有其他slot被占用,检查non_full_runs_是否记录过该run。如果一切run是full的,不在non_full_runs_之中,此时将它加入non_full_runs_。
· FreePages
更新对应地址上的page_map_标记为kPageMapEmpty,根据page_release_mode_判断是否要对该领域清0。
将释放掉的地址空间构造成一个新的FreePageRun,如果free_page_runs_集合不为空,则尝试着向低地址或者高地址合并,变成新的更大FreePageRun,插入free_page_runs_。此处会releasePages(1、memset清0,2、标记page_map_),但不会通过madvice置为MADV_DONTNEED,提高该段内存重用时的性能。
· Trim
获得free_page_runs_最尾部的free page run(未使用),memset清0或者通过madvice置为MADV_DONTNEED,更新footprinter。
· 初始化
Thread构造函数中会构造一个run* 数组rosalloc_runs。数组大小为34,对应于34个级别的run,不过此时的run并不可用,第一次使用的时候才会真正分配一个run。以后从thread local分配时,从rosalloc_runs取出对应级别的run进行分配。
· Alloc
在thread_local_run中调用AllocSlot分配空间。如果第一次分配不到内存,说明是首次调用,或者run已满。如果是run首次调用,refill这个run,如果是run已满,调用MergeThreadLocalFreeBitMapToAllocBitMap函数将thread local free bitmap合并到alloc bitmap中去。
thread local free bitmap在thread local run被free的时候才会被置,如果merge后返回为1(即thread local free bitmap被置为1过),说明thread local run被释放过,但是alloc bitmap还未同步,则更新alloc bitmap的信息,重新在这个run上进行分配。这么做的好处是:小额内存使用时候,不需要在共享内存上分配,防止加锁降低性能。
如果merge后bitmap显示该run还是full,则重新获得run,并将其作为新的thread local run,在新的thread local run分配slot。
· Free
调用MarkThreadLocalFreeBitMap函数,将该部分内存清0,将thread local bitmap中该slot位置置1
· BulkFree
该函数传进参数为地址数组,函数功能为批量Free。
1、 根据传进地址,决定释放run或者释放large object(即释放page,非物理page)。如果释放run,标记bulk free bitmap。
2、 如果释放的run为thread local run,将bulk free bitmap合并到thread local bitmap中去,如果为普通run,将bulk free bitmap合并到alloc bitmap中去。
3、 如果释放后的run为空并且不为当前使用的run,则free掉该run。
4、 如果释放后的run不为空且不为当前使用的run,则将该run插入到non_full_runs中。
标签:
原文地址:http://my.oschina.net/boolearner/blog/479909