jemalloc源码解读(五)内存布局

来源:互联网 发布:网络机房消防应急预案 编辑:程序博客网 时间:2024/04/29 20:07


    从《更好的内存管理-jemalloc》这边文章中,可以比较直接看到,在Jemalloc中,几个重要对象的关系,arena/bin/run之间关系。但是他没有揭示更深刻的东西。我们知道,arena包含多个bin,而bin也包含多个run。对于任何一个请求,根据size计算出,所在bin数组的下表。然后从这个bin中,提取合适的run来分配内存。这个大方向没有错,但如何实现就很讲究,下面我们来更深入的分析。

一、run的结构

   header + bitmap + region0 + ...+ regionx

  这个内存布局是动态的,根据arena_bin_info来确定的。

二、bin的结构  

struct arena_bin_s {malloc_mutex_tlock;arena_run_t*runcur;arena_run_tree_t runs;};
lock和runcur就没有什么好说的,最好玩的就是runs,后面再分析。

三、arena的结构

struct arena_s {malloc_mutex_tlock;arena_chunk_tree_tchunks_dirty;arena_chunk_t*spare;arena_avail_tree_truns_avail;arena_bin_tbins[NBINS];};

这里做了些裁剪,没有全部列出。到此为止,《更好的内存管理-jemalloc 》都介绍过了。我们来看更精彩的内容,我在上面的free过程分析中,一直强调chunk的分配方式是jemalloc的一个非常重要的基础,他的要点就是内存地址对齐,简单说,就是对于一个地址addr,通过CHUNK_ADDR2BASE宏就能直接得到所在的chunk。


下面,我们假设一个应用场景,我要分配一个大小为SIZE内存块,那么流程就是这样:

1、选定一个arena或者tcache,没啥好说的。

2、计算对应的对齐长度,选定arena中bins的下表。

3、从runcur或者runs选择一个run

4、从选定的run中,计算bitmap,得到空闲的region,后返回。

在正常情况下,这是个很完美的流程,没啥好说。但是出现没有足够内存情况下,问题就来了。需要从系统拉出一个新的Chunk来。让我们继续研究下chunk的结构,

struct arena_chunk_s {arena_t*arena;rb_node(arena_chunk_t)dirty_link;size_tndirty;size_tnruns_avail;size_tnruns_adjac;arena_chunk_map_tmap[1]; };
在这个结构中,map的结构是最精彩的。首先map是个数组,他的下标对应于run在这个chunk中的位置,从代码

static arena_run_t * arena_bin_runs_first(arena_bin_t *bin){arena_chunk_map_t *mapelm = arena_run_tree_first(&bin->runs);if (mapelm != NULL) {arena_chunk_t *chunk;size_t pageind;arena_run_t *run;chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(mapelm);pageind = ((((uintptr_t)mapelm - (uintptr_t)chunk->map) /    sizeof(arena_chunk_map_t))) + map_bias;run = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)((pageind -    arena_mapbits_small_runind_get(chunk, pageind)) <<    LG_PAGE));return (run);}return (NULL);}

中可以看到,CHUNK_ADDR2BASE宏又一次被完美应用。在前面,我们提到bin->runs是个最有意思的成员变量。因为runs里面的节点不是run而是run对应的arena_chunk_map_t,这个类型是对run的描述。他们之间的关系是pageind。计算mapelm到map的相对位置可以得到pageind,计算run到chunk的相对位置,同样可以得到相同的pageind。


解析到这里,我们可以得到几个重要结论。

其一、jemalloc的一个重要基石,就是CHUNK_ADDR2BASE,省了很多查找。

其二、chunk是从系统分配内存的的最小单位,但他本身包含了描述信息。

其三、run是内存分配的单元,其本身也包含了描述信息。


在jemalloc中,描述和数据的混合是一个重要特点。也是一个无奈之举,可以说是CHUNK_ADDR2BASE这把双刃剑的结果。




原创粉丝点击