From 0e9483510468714042f9164dba8a824b0c2c72c2 Mon Sep 17 00:00:00 2001 From: Kumar Aditya Date: Mon, 22 Dec 2025 14:53:30 +0530 Subject: [PATCH 1/4] avoid lock in tracemalloc in general case --- Include/internal/pycore_tracemalloc.h | 5 +++- Python/tracemalloc.c | 43 ++++++++++++++------------- 2 files changed, 27 insertions(+), 21 deletions(-) diff --git a/Include/internal/pycore_tracemalloc.h b/Include/internal/pycore_tracemalloc.h index 693385f9a46d12..9974ea3c4143fa 100644 --- a/Include/internal/pycore_tracemalloc.h +++ b/Include/internal/pycore_tracemalloc.h @@ -21,7 +21,10 @@ struct _PyTraceMalloc_Config { } initialized; /* Is tracemalloc tracing memory allocations? - Variable protected by the TABLES_LOCK(). */ + Variable protected by the TABLES_LOCK() and stored atomically. + Atomic store is used so that it can read without locking for the + general case of checking if tracemalloc is enabled. + */ int tracing; /* limit of the number of frames in a traceback, 1 by default. diff --git a/Python/tracemalloc.c b/Python/tracemalloc.c index 20351618721c3b..cb25df12132d39 100644 --- a/Python/tracemalloc.c +++ b/Python/tracemalloc.c @@ -850,7 +850,7 @@ _PyTraceMalloc_Start(int max_nframe) /* everything is ready: start tracing Python memory allocations */ TABLES_LOCK(); - tracemalloc_config.tracing = 1; + _Py_atomic_store_int_relaxed(&tracemalloc_config.tracing, 1); TABLES_UNLOCK(); return 0; @@ -867,7 +867,7 @@ _PyTraceMalloc_Stop(void) } /* stop tracing Python memory allocations */ - tracemalloc_config.tracing = 0; + _Py_atomic_store_int_relaxed(&tracemalloc_config.tracing, 0); /* unregister the hook on memory allocators */ PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw); @@ -1207,18 +1207,20 @@ int PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr, size_t size) { + if (_Py_atomic_load_int_relaxed(&tracemalloc_config.tracing) == 0) { + /* tracemalloc is not tracing: do nothing */ + return -2; + } PyGILState_STATE gil_state = PyGILState_Ensure(); TABLES_LOCK(); - - int result; - if (tracemalloc_config.tracing) { - result = tracemalloc_add_trace_unlocked(domain, ptr, size); - } - else { + // Check again now that we hold the lock + if (!tracemalloc_config.tracing) { + TABLES_UNLOCK(); + PyGILState_Release(gil_state); /* tracemalloc is not tracing: do nothing */ - result = -2; + return -2; } - + int result = tracemalloc_add_trace_unlocked(domain, ptr, size); TABLES_UNLOCK(); PyGILState_Release(gil_state); return result; @@ -1228,20 +1230,21 @@ PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr, int PyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr) { - TABLES_LOCK(); - - int result; - if (tracemalloc_config.tracing) { - tracemalloc_remove_trace_unlocked(domain, ptr); - result = 0; - } - else { + if (_Py_atomic_load_int_relaxed(&tracemalloc_config.tracing) == 0) { /* tracemalloc is not tracing: do nothing */ - result = -2; + return -2; } + TABLES_LOCK(); + // Check again now that we hold the lock + if (!tracemalloc_config.tracing) { + TABLES_UNLOCK(); + /* tracemalloc is not tracing: do nothing */ + return -2; + } + tracemalloc_remove_trace_unlocked(domain, ptr); TABLES_UNLOCK(); - return result; + return 0; } From 19f6c87a799b274129fe50dfa42d5303a6181393 Mon Sep 17 00:00:00 2001 From: Kumar Aditya Date: Mon, 22 Dec 2025 17:29:22 +0530 Subject: [PATCH 2/4] code review --- Python/tracemalloc.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/Python/tracemalloc.c b/Python/tracemalloc.c index cb25df12132d39..cdd96925d1f27a 100644 --- a/Python/tracemalloc.c +++ b/Python/tracemalloc.c @@ -1213,14 +1213,16 @@ PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr, } PyGILState_STATE gil_state = PyGILState_Ensure(); TABLES_LOCK(); - // Check again now that we hold the lock - if (!tracemalloc_config.tracing) { - TABLES_UNLOCK(); - PyGILState_Release(gil_state); + + int result; + if (tracemalloc_config.tracing) { + result = tracemalloc_add_trace_unlocked(domain, ptr, size); + } + else { /* tracemalloc is not tracing: do nothing */ - return -2; + result = -2; } - int result = tracemalloc_add_trace_unlocked(domain, ptr, size); + TABLES_UNLOCK(); PyGILState_Release(gil_state); return result; @@ -1236,15 +1238,19 @@ PyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr) } TABLES_LOCK(); - // Check again now that we hold the lock - if (!tracemalloc_config.tracing) { - TABLES_UNLOCK(); + + int result; + if (tracemalloc_config.tracing) { + tracemalloc_remove_trace_unlocked(domain, ptr); + result = 0; + } + else { /* tracemalloc is not tracing: do nothing */ - return -2; + result = -2; } - tracemalloc_remove_trace_unlocked(domain, ptr); + TABLES_UNLOCK(); - return 0; + return result; } From c4e9ed0bf80cdc440d26470bd3611cd8dfd1a5f8 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Mon, 22 Dec 2025 12:03:19 +0000 Subject: [PATCH 3/4] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2025-12-22-12-03-09.gh-issue-143057.Majsre.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-12-22-12-03-09.gh-issue-143057.Majsre.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-12-22-12-03-09.gh-issue-143057.Majsre.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-12-22-12-03-09.gh-issue-143057.Majsre.rst new file mode 100644 index 00000000000000..d4e48faed1045e --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-12-22-12-03-09.gh-issue-143057.Majsre.rst @@ -0,0 +1 @@ +Avoid locking in :c:func:`PyTraceMalloc_Track` when :mod:`tracemalloc` is not enabled. From ba336b19811c691f9952ce3fc6a49111901de67a Mon Sep 17 00:00:00 2001 From: Kumar Aditya Date: Mon, 22 Dec 2025 19:16:18 +0530 Subject: [PATCH 4/4] Update Misc/NEWS.d/next/Core_and_Builtins/2025-12-22-12-03-09.gh-issue-143057.Majsre.rst Co-authored-by: T. Wouters --- .../2025-12-22-12-03-09.gh-issue-143057.Majsre.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-12-22-12-03-09.gh-issue-143057.Majsre.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-12-22-12-03-09.gh-issue-143057.Majsre.rst index d4e48faed1045e..2eac8c1cfdc10c 100644 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-12-22-12-03-09.gh-issue-143057.Majsre.rst +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-12-22-12-03-09.gh-issue-143057.Majsre.rst @@ -1 +1 @@ -Avoid locking in :c:func:`PyTraceMalloc_Track` when :mod:`tracemalloc` is not enabled. +Avoid locking in :c:func:`PyTraceMalloc_Track` and :c:func:`PyTraceMalloc_Untrack` when :mod:`tracemalloc` is not enabled.