`
mqzhuang
  • 浏览: 185367 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

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 bin chunk 链表头,对 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_SZ 4B 的平台,小于 64B chunk 分配请求,对于 SIZE_SZ 8B 的平台,小于 128B chunk 分配请求,首先会查找 fast bins 中是否有所需大小的 chunk 存在(精确匹配),如果存在,就直接返回。

Fast bins 可以看着是 small bins 的一小部分 cache ,默认情况下, fast bins cache small bins 的前 7 个大小的空闲 chunk ,也就是说,对于 SIZE_SZ 4B 的平台, fast bins 7 chunk 空闲链表( bin ),每个 bin chunk 大小依次为 16B 24B 32B 40B 48B 56B 64B ;对于 SIZE_SZ 8B 的平台, fast bins 7 chunk 空闲链表( bin ),每个 bin chunk 大小依次为 32B 48B 64B 80B 96B 112B 128B 。以 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 bin index ,获得 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 bin fast bins 数组中的 index ,由于 bin[0] bin[1] 中的 chunk 不存在,所以需要减 2 ,对于 SIZE_SZ 4B 的平台,将 sz 除以 8 2 得到 fast bin index ,对于 SIZE_SZ 8B 的平台,将 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_SZ 4B 的平台,最大 chunk 64B ,对于 SIZE_SZ 8B 的平台,最大 chunk 128B ptmalloc 默认情况下调用 set_max_fast (s) 将全局变量 global_max_fast 设置为 DEFAULT_MXFAST ,也就是设置 fast bins chunk 的最大值, get_max_fast () 用于获得这个全局变量 global_max_fast 的值。

 

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics