Isolate the tracemalloc Module Between Interpreters #101520
Labels
3.12
new features, bugs and security fixes
interpreter-core
(Objects, Python, Grammar, and Parser dirs)
topic-subinterpreters
type-feature
A feature request or enhancement
(See #100227.)
Currently the tracemalloc module has some state in
_PyRuntimeState
, including objects, which is shared by all interpreters. Interpreters should be isolated from each other, for a variety of reasons (including the possibility of a per-interpreter GIL). Isolating the module will involve moving some of the state toPyInterpreterState
(and, under per-interpreter GIL, guarding other state with a global lock).Analysis:
(expand)
Allocators
The module installs a custom allocator (using the PEP 445 API
(docs).
(expand)
the allocator functions:
-
tracemalloc_alloc()
malloc()
orcalloc()
>-
tracemalloc_realloc()
realloc()
orfree()
>-
tracemalloc_raw_alloc()
tracemalloc_alloc()
*malloc()
orcalloc()
>-
tracemalloc_alloc_gil()
tracemalloc_alloc()
malloc()
orcalloc()
>tracemalloc_raw_malloc()
tracemalloc_alloc()
malloc()
>tracemalloc_raw_alloc()
tracemalloc_raw_calloc()
tracemalloc_alloc()
calloc()
>tracemalloc_raw_alloc()
tracemalloc_raw_realloc()
tracemalloc_realloc()
*realloc()
>tracemalloc_free()
free()
>tracemalloc_malloc_gil()
tracemalloc_alloc_gil()
tracemalloc_calloc_gil()
tracemalloc_alloc_gil()
tracemalloc_realloc_gil()
tracemalloc_realloc()
realloc()
>tracemalloc_free()
free()
>* Note that
tracemalloc_raw_alloc()
wraps thetracemalloc_alloc()
callwith
PyGILState_Ensure()
/PyGILState_Release()
.Likewise for
tracemalloc_raw_realloc()
where it callstracemalloc_realloc()
.In no other case does an allocator function use the GILState API for any calls.
State
Fields
(expand)
https://github.com/python/cpython/blob/main/Include/internal/pycore_tracemalloc.h#L57-L107
https://github.com/python/cpython/blob/main/Include/internal/pycore_runtime.h#L147
raw
cpython/Include/internal/pycore_tracemalloc.h
Lines 43 to 55 in 0675b8f
cpython/Include/internal/pycore_tracemalloc.h
Lines 57 to 64 in 0675b8f
cpython/Include/internal/pycore_tracemalloc.h
Lines 57 to 107 in 0675b8f
cpython/Modules/_tracemalloc.c
Lines 54 to 55 in 0675b8f
cpython/Modules/_tracemalloc.c
Lines 69 to 76 in 0675b8f
config
struct _PyTraceMalloc_Config
initialized
enum {}
tracing
bool
max_nframe
int
allocators
mem
PyMemAllocatorEx
raw
PyMemAllocatorEx
obj
PyMemAllocatorEx
tables_lock
PyThread_type_lock
TRACE_RAW_MALLOC
traced_memory
size_t
tables_lock
peak_traced_memory
size_t
tables_lock
filenames
_Py_hashtable_t *
set
of objectstraceback
struct tracemalloc_traceback *
tracebacks
_Py_hashtable_t *
set
oftraceback_t
traces
_Py_hashtable_t *
tables_lock
trace_t
domains
_Py_hashtable_t *
tables_lock
_Py_hashtable_t *
(per-domaintraces
)empty_traceback
struct tracemalloc_traceback
reentrant_key
Py_tss_t
notes:
struct tracemalloc_traceback
holds a filename objecttraceback_t
is a typedef forstruct tracemalloc_traceback
frame_t
is a typedef forstruct tracemalloc_frame
hold objects:
filenames
traceback
(filename in each frame)tracebacks
(filename in each frame of each traceback)traces
(filename in each frame of each traceback)domains
(filename in each frame of each traceback in each domain)Usage
(expand)
simple:
config
initialized
tracemalloc_init()
tracemalloc_deinit()
tracemalloc_init()
tracemalloc_deinit()
tracing
_tracemalloc_is_tracing_impl()
_tracemalloc__get_traces_impl()
_tracemalloc_clear_traces_impl()
_tracemalloc_get_traceback_limit_impl()
_tracemalloc_get_traced_memory_impl()
_tracemalloc_reset_peak_impl()
PyTraceMalloc_Track()
PyTraceMalloc_Untrack()
_PyTraceMalloc_NewReference()
_PyMem_DumpTraceback()
tracemalloc_start()
tracemalloc_stop()
tracemalloc_start()
tracemalloc_stop()
tracemalloc_get_traceback()
max_nframe
_tracemalloc_get_traceback_limit_impl()
tracemalloc_start()
traceback_get_frames()
allocators
mem
tracemalloc_start()
+tracemalloc_stop()
raw
tracemalloc_init()
+tracemalloc_start()
+tracemalloc_stop()
raw_malloc()
raw_free()
obj
tracemalloc_start()
+tracemalloc_stop()
tables_lock
_tracemalloc__get_traces_impl()
+_tracemalloc_get_tracemalloc_memory_impl()
+_tracemalloc_get_traced_memory_impl()
+_tracemalloc_reset_peak_impl()
+PyTraceMalloc_Track()
+PyTraceMalloc_Untrack()
+_PyTraceMalloc_NewReference()
+tracemalloc_init()
tracemalloc_deinit()
tracemalloc_init()
*tracemalloc_deinit()
*tracemalloc_alloc()
+tracemalloc_realloc()
+tracemalloc_free()
+tracemalloc_realloc_gil()
+tracemalloc_raw_realloc()
+tracemalloc_get_traceback()
+tracemalloc_clear_traces()
+traced_memory
_tracemalloc_get_traced_memory_impl()
_tracemalloc_reset_peak_impl()
tracemalloc_add_trace()
tracemalloc_add_trace()
tracemalloc_remove_trace()
tracemalloc_clear_traces()
peak_traced_memory
_tracemalloc_get_traced_memory_impl()
_tracemalloc_reset_peak_impl()
tracemalloc_add_trace()
tracemalloc_add_trace()
tracemalloc_clear_traces()
filenames
_tracemalloc_get_tracemalloc_memory_impl()
tracemalloc_init()
*tracemalloc_get_frame()
tracemalloc_clear_traces()
+traceback
tracemalloc_stop()
tracemalloc_start()
*tracemalloc_stop()
*traceback_new()
+tracebacks
_tracemalloc_get_tracemalloc_memory_impl()
tracemalloc_init()
*tracemalloc_deinit()
+traceback_new()
+tracemalloc_clear_traces()
+traces
_tracemalloc__get_traces_impl()
_tracemalloc_get_tracemalloc_memory_impl()
_PyTraceMalloc_NewReference()
tracemalloc_deinit()
+tracemalloc_init()
*tracemalloc_get_traces_table()
tracemalloc_add_trace()
(indirect)tracemalloc_remove_trace()
(indirect)tracemalloc_get_traceback()
(indirect)tracemalloc_clear_traces()
+domains
_tracemalloc__get_traces_impl()
_tracemalloc_get_tracemalloc_memory_impl()
tracemalloc_deinit()
+tracemalloc_init()
*tracemalloc_get_traces_table()
tracemalloc_remove_trace()
(indirect)tracemalloc_get_traceback()
(indirect)tracemalloc_clear_traces()
+tracemalloc_add_trace()
+empty_traceback
tracemalloc_init()
+traceback_new()
reentrant_key
tracemalloc_init()
+tracemalloc_deinit()
+tracemalloc_alloc_gil()
(indirect) +tracemalloc_realloc_gil()
(indirect) +tracemalloc_raw_alloc()
(indirect) +tracemalloc_raw_realloc()
(indirect) +get_reentrant()
set_reentrant()
+* the function allocates/deallocates the value (see below)
+ the function mutates the value (see below)
simple (extraneous):
config.tracing
tracemalloc_add_trace()
tracemalloc_remove_trace()
tables_lock
tracemalloc_init()
tracemalloc_deinit()
traced_memory
tracemalloc_remove_trace()
filenames
tracemalloc_init()
traceback
tracemalloc_start()
tracemalloc_stop()
tracemalloc_start()
tracebacks
tracemalloc_init()
traces
tracemalloc_init()
domains
tracemalloc_init()
mutation of complex fields:
allocators.mem
tracemalloc_start()
allocators.raw
tracemalloc_init()
tracemalloc_start()
allocators.obj
tracemalloc_start()
tables_lock
_tracemalloc__get_traces_impl()
_tracemalloc_get_tracemalloc_memory_impl()
_tracemalloc_get_traced_memory_impl()
_tracemalloc_reset_peak_impl()
PyTraceMalloc_Track()
PyTraceMalloc_Untrack()
_PyTraceMalloc_NewReference()
tracemalloc_alloc()
tracemalloc_alloc()
tracemalloc_realloc()
tracemalloc_free()
tracemalloc_realloc_gil()
tracemalloc_raw_realloc()
tracemalloc_clear_traces()
tracemalloc_get_traceback()
filenames
tracemalloc_clear_traces()
tracemalloc_get_frame()
tracemalloc_clear_traces()
tracemalloc_deinit()
traceback
traceback_new()
tracebacks
tracemalloc_deinit()
tracemalloc_clear_traces()
traceback_new()
traces
tracemalloc_deinit()
tracemalloc_clear_traces()
domains
tracemalloc_deinit()
tracemalloc_clear_traces()
tracemalloc_add_trace()
reentrant_key
tracemalloc_init()
tracemalloc_deinit()
set_reentrant()
indirection:
allocators.raw
tracemalloc_start()
tracemalloc_copy_trace()
raw_malloc()
tracemalloc_stop()
raw_free()
traceback_new()
tracemalloc_add_trace()
tracemalloc_copy_trace()
raw_malloc()
traceback_new()
tracemalloc_add_trace()
tracemalloc_remove_trace()
raw_free()
traces
tracemalloc_add_trace()
tracemalloc_remove_trace()
tracemalloc_get_traceback()
tracemalloc_get_traces_table()
domains
tracemalloc_add_trace()
tracemalloc_remove_trace()
tracemalloc_get_traceback()
tracemalloc_get_traces_table()
reentrant_key
tracemalloc_alloc_gil()
tracemalloc_realloc_gil()
tracemalloc_raw_alloc()
tracemalloc_raw_realloc()
get_reentrant()
tracemalloc_alloc_gil()
tracemalloc_realloc_gil()
tracemalloc_raw_alloc()
tracemalloc_raw_realloc()
set_reentrant()
Linked PRs
The text was updated successfully, but these errors were encountered: