Prérequis

Hello ! o/

TCache, ou Thread Local Cache a été implémenté depuis glibc 2.26, c’est à dire fin aout 2017. Il a permis de gagner d’importantes performances. Chaque thread contient une variable locale threadée qui se souvient de quelle arena il a utilisé en dernier. Si cette arena est en utilisation quand notre thread veut l’utiliser, le thread se bloque et attend que le mutex soit libre. Par conséquent nous allons introduire 2 nouvelles structures de données:

typedef struct tcache_entry
{
  struct tcache_entry *next;
  struct tcache_perthread_struct *key; // double free detection
} tcache_entry;

typedef struct tcache_perthread_struct
{
  char counts[TCACHE_MAX_BINS];
  tcache_entry *entries[TCACHE_MAX_BINS];
} tcache_perthread_struct;

static __thread tcache_perthread_struct *tcache = NULL;

Chaque thread contient tcache qui contient donc un petit nombre de chunks free qui peuvent être accéder sans besoin de locker une arena. tcache_entry pointe les chunks dans une list chaînée, comme pour les fastbins mais qui pointe sur le user data. Le tableau entries de tcache_perthread_struct est indexé par taille de chunk de 12 à 516 par pas de 8 en x86, et de 24 à 1032 par pas de 16 en x86-64.

Source: MallocInternals - glibc wiki

Donc forcément, avant de tomber dans une fastbin, free peut faire tomber le chunk dans le tcache ! Et donc l’accès au tcache sera plus rapide qu’aux fastbins, ce qui en fait une structure très intéressante d’un point de vue performance. Si vous voulez en savoir plus sur le tcache dans un contexte encore plus bas-niveau, je vous recommande cet article.

Merci pour votre lecture :)