workspace/tags/glibc/

Glibc

  • 2.4x 的 tcache 机制分析

    简述

    在 2.39 到 2.40 中,malloc.c 并未发生变化,因此我们这里主要讲一些 2.41 到 2.43 的 tcache 相关的一些小细节 在这三个版本中,主要变化可以简单概括为

    • 2.41:
      • calloc 可以分配 tcache 块
      • 小 chunk 被 free 后会直接进入 small bin
    • 2.42
      • large_tcache 的引入
    • 2.43
      • tcache 扩容以补偿 fastbin 删除的性能问题
      • large_tcache 分配改为需要精确 chunk_size
      • mmap chunk 可以进入 tcache

    因为 tcache 初始化时机这几个版本一直改来改去的很乱,只做简述 以下为细分的分析,我会粘贴一些源码辅助理解

    tcache 基本机制

    tcache 结构体的变化

    在 glibc 2.42版本中,tcache_perthread_struct 结构进行了调整

    • 2.41
    /* We overlay this structure on the user-data portion of a chunk when
       the chunk is stored in the per-thread cache.  */
    typedef struct tcache_entry
    {
      struct tcache_entry *next;
      /* This field exists to detect double frees.  */
      uintptr_t key;
    } tcache_entry;
    
    /* There is one of these for each thread, which contains the
       per-thread cache (hence "tcache_perthread_struct").  Keeping
       overall size low is mildly important.  Note that COUNTS and ENTRIES
       are redundant (we could have just counted the linked list each
       time), this is for performance reasons.  */
    typedef struct tcache_perthread_struct
    {
      uint16_t counts[TCACHE_MAX_BINS];
      tcache_entry *entries[TCACHE_MAX_BINS];
    } tcache_perthread_struct;
    
    static __thread bool tcache_shutting_down = false;
    static __thread tcache_perthread_struct *tcache = NULL;
    
    • 2.42
    /* We overlay this structure on the user-data portion of a chunk when
       the chunk is stored in the per-thread cache.  */
    typedef struct tcache_entry
    {
      struct tcache_entry *next;
      /* This field exists to detect double frees.  */
      uintptr_t key;
    } tcache_entry;
    
    /* There is one of these for each thread, which contains the
       per-thread cache (hence "tcache_perthread_struct").  Keeping
       overall size low is mildly important.  The 'entries' field is linked list of
       free blocks, while 'num_slots' contains the number of free blocks that can
       be added.  Each bin may allow a different maximum number of free blocks,
       and can be disabled by initializing 'num_slots' to zero.  */
    typedef struct tcache_perthread_struct
    {
      uint16_t num_slots[TCACHE_MAX_BINS];
      tcache_entry *entries[TCACHE_MAX_BINS];
    } tcache_perthread_struct;
    

    entry 的部分基本没有变化,这里主要变化还是原本的 counts 数组变成了 num_slots 数组 原本的 counts 数组表示对应索引下 tcache 链表的长度,现在 num_slots 数组中变为了对应索引下设剩下的空槽位

Terminal

C0nvR3 Lab terminal ready. Type help for commands.