[PATCH] malloc: move tcache_init out of hot tcache paths

Cupertino Miranda cupertino.miranda@oracle.com
Fri Apr 11 09:07:58 GMT 2025


Hi everyone,

Looking forward to your review.
I will reply to this patch with some benchmarking charts on a small
machine x86 machinei (AMD GX-222GC SOC).
In any case the content of the patch can only improve performance.

Cheers,
Cupertino

---

This patch moves any calls of tcache_init away after tcache hot paths.
Since there is no reazon to initialize tcaches in the hot path and
since we need to be able to check tcache != NULL in any case, because of
tcache_thread_shutdown function, moving tcache_init away from hot path
can only be beneficial.
It adds 2 extra checks for tcache != NULL in non regular allocation
paths to resolve regressions.

---
 malloc/malloc.c | 21 ++++++++++++---------
 1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/malloc/malloc.c b/malloc/malloc.c
index a0bc733482..ed7f271693 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -3345,6 +3345,7 @@ tcache_init(void)
   if (__glibc_unlikely (tcache == NULL)) \
     tcache_init();
 
+
 /* Trying to alloc BYTES from tcache. If tcache is available, chunk
    is allocated and stored to MEMPTR, otherwise, MEMPTR is NULL.
    It returns true if error occurs, else false. */
@@ -3361,13 +3362,16 @@ tcache_try_malloc (size_t bytes, void **memptr)
 
   size_t tc_idx = csize2tidx (tbytes);
 
-  MAYBE_INIT_TCACHE ();
 
   if (tcache_available (tc_idx))
-    *memptr = tcache_get (tc_idx);
+    {
+      *memptr = tcache_get (tc_idx);
+      return false;
+    }
   else
     *memptr = NULL;
 
+  MAYBE_INIT_TCACHE ();
   return false;
 }
 
@@ -3393,8 +3397,6 @@ __libc_malloc2 (size_t bytes)
   if (!__malloc_initialized)
     ptmalloc_init ();
 
-  MAYBE_INIT_TCACHE ();
-
   if (SINGLE_THREAD_P)
     {
       victim = tag_new_usable (_int_malloc (&main_arena, bytes));
@@ -3433,6 +3435,8 @@ __libc_malloc (size_t bytes)
 
   if (tcache_available (tc_idx))
     return tag_new_usable (tcache_get (tc_idx));
+  else
+    MAYBE_INIT_TCACHE ();
 #endif
 
   return __libc_malloc2 (bytes);
@@ -3474,8 +3478,6 @@ __libc_free (void *mem)
     }
   else
     {
-      MAYBE_INIT_TCACHE ();
-
       /* Mark the chunk as belonging to the library again.  */
       (void)tag_region (chunk2mem (p), memsize (p));
 
@@ -3696,8 +3698,6 @@ _mid_memalign (size_t alignment, size_t bytes, void *address)
       }
     size_t tc_idx = csize2tidx (tbytes);
 
-    MAYBE_INIT_TCACHE ();
-
     if (tcache_available (tc_idx))
       {
 	/* The tcache itself isn't encoded, but the chain is.  */
@@ -3715,6 +3715,7 @@ _mid_memalign (size_t alignment, size_t bytes, void *address)
 	  }
       }
   }
+  MAYBE_INIT_TCACHE ();
 #endif
 
   if (SINGLE_THREAD_P)
@@ -4299,6 +4300,7 @@ _int_malloc (mstate av, size_t bytes)
 	 filling the cache, return one of the cached ones.  */
       ++tcache_unsorted_count;
       if (return_cached
+	  && __glibc_likely (tcache != NULL)
 	  && mp_.tcache_unsorted_limit > 0
 	  && tcache_unsorted_count > mp_.tcache_unsorted_limit)
 	{
@@ -4313,7 +4315,8 @@ _int_malloc (mstate av, size_t bytes)
 
 #if USE_TCACHE
       /* If all the small chunks we found ended up cached, return one now.  */
-      if (return_cached)
+      if (return_cached
+	  && __glibc_likely (tcache != NULL))
 	{
 	  return tcache_get (tc_idx);
 	}
-- 
2.30.2



More information about the Libc-alpha mailing list