Glibc内存管理--ptmalloc2源代码分析(十五)

5.2.3 Unsorted bin

        Unsorted bin 可以看作是 small bins 和 large bins 的 cache ,只有一个 unsorted bin ,以双向链表管理空闲 chunk ,空闲 chunk 不排序,所有的 chunk 在回收时都要先放到 unsorted bin 中,分配时,如果在 unsorted bin 中没有合适的 chunk ,就会把 unsorted bin 中的所有 chunk 分别加入到所属的 bin 中,然后再在 bin 中分配合适的 chunk 。 Bins 数组中的元素 bin[1] 用于存储 unsorted bin 的 chunk 链表头。

/*
  Unsorted chunks

    All remainders from chunk splits, as well as all returned chunks,
    are first placed in the "unsorted" bin. They are then placed
    in regular bins after malloc gives them ONE chance to be used before
    binning. So, basically, the unsorted_chunks list acts as a queue,
    with chunks being placed on it in free (and malloc_consolidate),
    and taken off (to be either used or placed in bins) in malloc.

    The NON_MAIN_ARENA flag is never set for unsorted chunks, so it
    does not have to be taken into account in size comparisons.
*/

/* The otherwise unindexable 1-bin is used to hold unsorted chunks. */
#define unsorted_chunks(M)          (bin_at(M, 1))

/*
  Top

    The top-most available chunk (i.e., the one bordering the end of
    available memory) is treated specially. It is never included in
    any bin, is used only if no other chunk is available, and is
    released back to the system if it is very large (see
    M_TRIM_THRESHOLD).  Because top initially
    points to its own bin with initial zero size, thus forcing
    extension on the first malloc request, we avoid having any special
    code in malloc to check whether it even exists yet. But we still
    need to do so when getting memory from system, so we make
    initial_top treat the bin as a legal but unusable chunk during the
    interval between initialization and the first call to
    sYSMALLOc. (This is somewhat delicate, since it relies on
    the 2 preceding words to be zero during this interval as well.)
*/

/* Conveniently, the unsorted bin can be used as dummy top on first call */
#define initial_top(M)              (unsorted_chunks(M))

 

上面的宏的定义比较明显,把 bin[1] 设置为 unsorted binchunk 链表头,对 top chunk 的初始化,也暂时把 top chunk 初始化为 unsort chunk ,仅仅是初始化一个值而已,这个 chunk 的内容肯定不能用于 top chunk 来分配内存,主要原因是 top chunk 不属于任何 bin ,但 ptmalloc 中的一些 check 代码,可能需要 top chunk 属于一个合法的 bin

 

5.2.4   Fast bins

Fast bins 主要是用于提高小内存的分配效率,默认情况下, 对于 SIZE_SZ4B 的平台,小于 64Bchunk 分配请求,对于 SIZE_SZ8B 的平台,小于 128Bchunk 分配请求,首先会查找 fast bins 中是否有所需大小的 chunk 存在(精确匹配),如果存在,就直接返回。

Fast bins 可以看着是 small bins 的一小部分 cache ,默认情况下, fast binscachesmall bins 的前 7 个大小的空闲 chunk ,也就是说,对于 SIZE_SZ4B 的平台, fast bins7chunk 空闲链表( bin ),每个 binchunk 大小依次为 16B24B32B40B48B56B64B ;对于 SIZE_SZ8B 的平台, fast bins7chunk 空闲链表( bin ),每个 binchunk 大小依次为 32B48B64B80B96B112B128B 。以 32 为系统为例,分配的内存大小与 chunk 大小和 fast bins 的对应关系如下表所示:

Fast bins 可以看着是 LIFO 的栈,使用单向链表实现。

/*
  Fastbins

    An array of lists holding recently freed small chunks.  Fastbins
    are not doubly linked.  It is faster to single-link them, and
    since chunks are never removed from the middles of these lists,
    double linking is not necessary. Also, unlike regular bins, they
    are not even processed in FIFO order (they use faster LIFO) since
    ordering doesn't much matter in the transient contexts in which
    fastbins are normally used.

    Chunks in fastbins keep their inuse bit set, so they cannot
    be consolidated with other free chunks. malloc_consolidate
    releases all chunks in fastbins and consolidates them with
    other free chunks.
*/
typedef struct malloc_chunk* mfastbinptr;
#define fastbin(ar_ptr, idx) ((ar_ptr)->fastbinsY[idx])

 

根据 fast binindex ,获得 fast bin 的地址。 Fast bins 的数字定义在 malloc_state 中, 5.3 节会做详细介绍。

/* offset 2 to use otherwise unindexable first 2 bins */
#define fastbin_index(sz) \
  ((((unsigned int)(sz)) >> (SIZE_SZ == 8 ? 4 : 3)) - 2)

fastbin_index(sz) 用于获得 fast binfast bins 数组中的 index ,由于 bin[0]bin[1] 中的 chunk 不存在,所以需要减 2 ,对于 SIZE_SZ4B 的平台,将 sz 除以 82 得到 fast bin index ,对于 SIZE_SZ8B 的平台,将 sz 除以 16 减去 2 得到 fast bin index

/* The maximum fastbin request size we support */
#define MAX_FAST_SIZE     (80 * SIZE_SZ / 4)
#define NFASTBINS  (fastbin_index(request2size(MAX_FAST_SIZE))+1)

/*
  FASTBIN_CONSOLIDATION_THRESHOLD is the size of a chunk in free()
  that triggers automatic consolidation of possibly-surrounding
  fastbin chunks. This is a heuristic, so the exact value should not
  matter too much. It is defined at half the default trim threshold as a
  compromise heuristic to only attempt consolidation if it is likely
  to lead to trimming. However, it is not dynamically tunable, since
  consolidation reduces fragmentation surrounding large chunks even
  if trimming is not used.
*/
#define FASTBIN_CONSOLIDATION_THRESHOLD  (65536UL)

  根据SIZE_SZ 的 不同大小, 定义 MAX_FAST_SIZE 为 80B 或是 160B , fast bins 数组的大小 NFASTBINS 为 10 , FASTBIN_CONSOLIDATION_THRESHOLD 为 64k ,当每次释放的 chunk 与该 chunk 相邻的空闲 chunk 合并后的大小大于 64k 时,就认为内存碎片可能比较多了,就需要把 fast bins 中的所有 chunk 都进行合并,以减少内存碎片对系统的影响。

#ifndef DEFAULT_MXFAST
#define DEFAULT_MXFAST     (64 * SIZE_SZ / 4)
#endif
/*
   Set value of max_fast.
   Use impossibly small value if 0.
   Precondition: there are no existing fastbin chunks.
   Setting the value clears fastchunk bit but preserves noncontiguous bit.
*/
#define set_max_fast(s) \
  global_max_fast = (((s) == 0)                                               \
                     ? SMALLBIN_WIDTH: ((s + SIZE_SZ) & ~MALLOC_ALIGN_MASK))
#define get_max_fast() global_max_fast

 上面的宏 DEFAULT_MXFAST 定义了默认的 fast bins 中最大的 chunk 大小,对于 SIZE_SZ4B 的平台,最大 chunk64B ,对于 SIZE_SZ8B 的平台,最大 chunk128Bptmalloc 默认情况下调用 set_max_fast (s) 将全局变量 global_max_fast 设置为 DEFAULT_MXFAST ,也就是设置 fast binschunk 的最大值, get_max_fast () 用于获得这个全局变量 global_max_fast 的值。

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值