jemalloc 深入分析 之 bitmap的两种实现

为了更好的阅读效果,推荐下载pdf文档:
详细文章请参考:《jemalloc 深入分析》
https://github.com/everschen/tools/blob/master/DOC/Jemalloc.pdf
https://download.csdn.net/download/ip5108/10941278

2.2. bitmap的两种实现

2.2.1. 什么时候使用bitmap TREE
/*

  • Do some analysis on how big the bitmap is before we use a tree. For a brute
  • force linear search, if we would have to call ffs_lu() more than 2^3 times,
  • use a tree instead.
    */
    #if LG_BITMAP_MAXBITS - LG_BITMAP_GROUP_NBITS > 3

define USE_TREE

#endif
LG_BITMAP_MAXBITS= LG_RUN_MAXREGS= (LG_PAGE - LG_TINY_MIN)=12-3=9
LG_BITMAP_GROUP_NBITS= (LG_SIZEOF_BITMAP + 3)= LG_SIZEOF_LONG+3
=6(64bit)或者5(32bit)。
Jemalloc 深入分析
Copyright 2013 Spreadtrum Communications Inc. 10
/* sizeof(long) == 2^LG_SIZEOF_LONG. /
#ifdef LP64
#define LG_SIZEOF_LONG 3
#else
#define LG_SIZEOF_LONG 2
#endif
LG_BITMAP_MAXBITS - LG_BITMAP_GROUP_NBITS=9-6/5,所以在64bit的时候不定义USE_TREE,在32bit的时候定义了USE_TREE。
64bit的时候,ffs_lu调用23=8次,超过8次就用TREE。32bit的时候ffs_lu调用24=16次,所以使用了TREE,看看效果如何?
/
Number of groups required to store a given number of bits. /
#define BITMAP_BITS2GROUPS(nbits)
((nbits + BITMAP_GROUP_NBITS_MASK=31) >> LG_BITMAP_GROUP_NBITS=5)
#elif LG_BITMAP_MAXBITS <= LG_BITMAP_GROUP_NBITS * 2
#define BITMAP_GROUPS_MAX BITMAP_GROUPS_2_LEVEL(BITMAP_MAXBITS)
LG_BITMAP_MAXBITS=9 <= LG_BITMAP_GROUP_NBITS * 2=5
5=10
BITMAP_MAXBITS=2^9
BITMAP_GROUPS_2_LEVEL(BITMAP_MAXBITS)=
#define BITMAP_GROUPS_L0(nbits)
BITMAP_BITS2GROUPS(nbits)
#define BITMAP_GROUPS_L1(nbits)
BITMAP_BITS2GROUPS(BITMAP_BITS2GROUPS(nbits))
#define BITMAP_GROUPS_1_LEVEL(nbits)
BITMAP_GROUPS_L0(nbits)
#define BITMAP_GROUPS_2_LEVEL(nbits) \ (BITMAP_GROUPS_1_LEVEL(nbits) + BITMAP_GROUPS_L1(nbits))
BITMAP_GROUPS_1_LEVEL(512)=BITMAP_GROUPS_L0(512)= BITMAP_BITS2GROUPS(512)=(512+31)>>5=16 BITMAP_GROUPS_L1(512)= BITMAP_BITS2GROUPS(16)=1
BITMAP_GROUPS_2_LEVEL(512)=16+1=17
Jemalloc 深入分析
Copyright 2013 Spreadtrum Communications Inc. 11
BITMAP_GROUPS_MAX=17

2.2.2. bitmap TREE设计
USE_TREE时,level[0]还是放置所有的groups,然后每往上一层,该层的每一位对应下层的一个bitmap。如此往上,直到最高层只有一个bitmap为止。
在这里插入图片描述
512/32=16,所以这里共需要16个bitmap,每一个bitmap是32位的字节。

2.2.3. bitmap_sfu的处理过程
bitmap_sfu(bitmap_t *bitmap, const bitmap_info_t binfo)
{
size_t bit;
bitmap_t g;
unsigned i;
assert(!bitmap_full(bitmap, binfo));
#ifdef USE_TREE i = binfo->nlevels - 1;//得到顶层level g = bitmap[binfo->levels[i].group_offset];//得到顶层bitmap值
bit = ffs_lu(g) - 1;
Jemalloc 深入分析
Copyright 2013 Spreadtrum Communications Inc. 12
while (i > 0) {
i–; g = bitmap[binfo->levels[i].group_offset + bit];//得到下一层bit位对应的bitmap值 bit = (bit << LG_BITMAP_GROUP_NBITS) + (ffs_lu(g) - 1);//得到下一层的bit所在的值,bit << LG_BITMAP_GROUP_NBITS表示上一层的每一个单位值需要乘以32,表示下层的一个字节跨度。
}
#else
i = 0;
g = bitmap[0]; while ((bit = ffs_lu(g)) == 0) {
i++;
g = bitmap[i];
}
bit = (i << LG_BITMAP_GROUP_NBITS) + (bit - 1);
#endif
bitmap_set(bitmap, binfo, bit);
return (bit);
}
— Built-in Function: int __builtin_ffsl (unsigned long)
Returns one plus the index of the least significant 1-bit of x, or if x is zero, returns zero.
返回右起第一个‘1’的位置。
如果是TREE方式,需要从root group开始往下查找,相比非TREE的方式也会更快。按16个bitmaps为例,只需要调用ffs_lu() 2次。而非TREE方式,平均会在4次。
LG_BITMAP_GROUP_NBITS=6,i<<6=i
64,一个bitmap是标识64个regions。

2.2.4. bitmap初始化过程
void
bitmap_init(bitmap_t *bitmap, const bitmap_info_t *binfo)
{
size_t extra;
Jemalloc 深入分析
Copyright 2013 Spreadtrum Communications Inc. 13
memset(bitmap, 0xffU, bitmap_size(binfo));
extra=(BITMAP_GROUP_NBITS-(binfo->nbits&BITMAP_GROUP_NBITS_MASK))
& BITMAP_GROUP_NBITS_MASK;
if (extra != 0)
bitmap[binfo->ngroups - 1] >>= extra;
}
extra是多余的标志位,对于64位系统,extra的计算过程如下:
extra=(64-(binfo->nbits&63))& 63;
所以当nbits(extra是2的次幂形式)大于等于64的,extra=0,当nbits小于64时,extra=64-nbits。然后把最后一个bitmap的高extra位置0,即右移extra位。
对于使用TREE时的bitmap_init,除了level0的extra置0,还需要往上把其他的查找bitmap的extra位置0。
bitmap_init(bitmap_t *bitmap, const bitmap_info_t binfo)
{
size_t extra;
unsigned i;
/

  • Bits are actually inverted with regard to the external bitmap
  • interface, so the bitmap starts out with all 1 bits, except for
  • trailing unused bits (if any). Note that each group uses bit 0 to
  • correspond to the first logical bit in the group, so extra bits
  • are the most significant bits of the last group.
    */
    memset(bitmap, 0xffU, bitmap_size(binfo));
    extra = (BITMAP_GROUP_NBITS - (binfo->nbits & BITMAP_GROUP_NBITS_MASK))
    & BITMAP_GROUP_NBITS_MASK;
    if (extra != 0)
    bitmap[binfo->levels[1].group_offset - 1] >>= extra;
    for (i = 1; i < binfo->nlevels; i++) {
    size_t group_count = binfo->levels[i].group_offset -
    binfo->levels[i-1].group_offset;
    Jemalloc 深入分析
    Copyright 2013 Spreadtrum Communications Inc. 14
    extra = (BITMAP_GROUP_NBITS - (group_count &
    BITMAP_GROUP_NBITS_MASK)) & BITMAP_GROUP_NBITS_MASK;
    if (extra != 0)
    bitmap[binfo->levels[i+1].group_offset - 1] >>= extra;
    }
    }

2.2.5. bitmap_info初始化过程
1)对于非TREE的模式,只需要计算ngroups,这里是64bit的系统。
binfo->ngroups = BITMAP_BITS2GROUPS(nbits);
/* Number of groups required to store a given number of bits. */
#define BITMAP_BITS2GROUPS(nbits)
((nbits + BITMAP_GROUP_NBITS_MASK) >> LG_BITMAP_GROUP_NBITS)
也就是:binfo->ngroups =(nbits+63)/64
2)对于TREE的模式,这里是32bit的系统。
首先置level0的group 偏移从第0个开始,binfo->levels[0].group_offset = 0;
然后下一个level的group偏移,是上一个level的偏移+group数量。
binfo->levels[i].group_offset = binfo->levels[i-1].group_offset+ group_count;
然后再把这一级的group数量作为nbits来计算下一级的group数量,
group_count = BITMAP_BITS2GROUPS(group_count);
这样计算,直到group_count为1为止。
为1后,把最后一个偏移保存在最高一级level中,实际这一级不作为查询的bitmap,只是作为group数量的返回值,因为group计算从0开始,这里group_count=1,加上去后刚好是group的个数。这个i会保存为binfo->nlevels,后续所有的处理都是i < binfo->nlevels也说明这层实际不存bitmap。
binfo->levels[i].group_offset = binfo->levels[i-1].group_offset+ group_count;

2.2.6. bitmap_full检测
对于TREE,只需要检查root group是否为0,也就是最后一个bitmap。
对于非TREE,需要逐个检查,最坏的情况下是检查8个bitmaps。
Jemalloc 深入分析
Copyright 2013 Spreadtrum Communications Inc. 15

2.2.7. bitmap_set
对于非TREE,直接把对应bitmap的对应位置0。
对于TREE,首先也需要把对应bitmap的对应位置0,然后如果这个bitmap值为0后,需要把level1的对应的bitmap位置0,如果这个时候这个bitmap值也为0,则需要继续往上对查找bitmap置0的动作,直到i == binfo->nlevels或者当前的bitmap不为0为止。

2.2.8. bitmap_sfu
对于非TREE,直接通过循环查找bitmap不为0的bit。
对于TREE,需要从上往下通过查找bitmap来找,对于32bit系统,理论上是32分查找,而且最大查找次数为BITMAP_MAX_LEVELS=5,实际一般2次就完成,远远小于非TREE的最大8次ffs_lu操作。

详细文章请参考:《jemalloc 深入分析》
https://github.com/everschen/tools/blob/master/DOC/Jemalloc.pdf
https://download.csdn.net/download/ip5108/10941278

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值