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
configstruct _PyTraceMalloc_Configinitializedenum {}tracingboolmax_nframeintallocatorsmemPyMemAllocatorExrawPyMemAllocatorExobjPyMemAllocatorExtables_lockPyThread_type_lockTRACE_RAW_MALLOCtraced_memorysize_ttables_lockpeak_traced_memorysize_ttables_lockfilenames_Py_hashtable_t *setof objectstracebackstruct tracemalloc_traceback *tracebacks_Py_hashtable_t *setoftraceback_ttraces_Py_hashtable_t *tables_locktrace_tdomains_Py_hashtable_t *tables_lock_Py_hashtable_t *(per-domaintraces)empty_tracebackstruct tracemalloc_tracebackreentrant_keyPy_tss_tnotes:
struct tracemalloc_tracebackholds a filename objecttraceback_tis a typedef forstruct tracemalloc_tracebackframe_tis a typedef forstruct tracemalloc_framehold objects:
filenamestraceback(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:
configinitializedtracemalloc_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()allocatorsmemtracemalloc_start()+tracemalloc_stop()rawtracemalloc_init()+tracemalloc_start()+tracemalloc_stop()raw_malloc()raw_free()objtracemalloc_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()+tracebacktracemalloc_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_tracebacktracemalloc_init()+traceback_new()reentrant_keytracemalloc_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.tracingtracemalloc_add_trace()tracemalloc_remove_trace()tables_locktracemalloc_init()tracemalloc_deinit()traced_memorytracemalloc_remove_trace()filenamestracemalloc_init()tracebacktracemalloc_start()tracemalloc_stop()tracemalloc_start()tracebackstracemalloc_init()tracestracemalloc_init()domainstracemalloc_init()mutation of complex fields:
allocators.memtracemalloc_start()allocators.rawtracemalloc_init()tracemalloc_start()allocators.objtracemalloc_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()filenamestracemalloc_clear_traces()tracemalloc_get_frame()tracemalloc_clear_traces()tracemalloc_deinit()tracebacktraceback_new()tracebackstracemalloc_deinit()tracemalloc_clear_traces()traceback_new()tracestracemalloc_deinit()tracemalloc_clear_traces()domainstracemalloc_deinit()tracemalloc_clear_traces()tracemalloc_add_trace()reentrant_keytracemalloc_init()tracemalloc_deinit()set_reentrant()indirection:
allocators.rawtracemalloc_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()tracestracemalloc_add_trace()tracemalloc_remove_trace()tracemalloc_get_traceback()tracemalloc_get_traces_table()domainstracemalloc_add_trace()tracemalloc_remove_trace()tracemalloc_get_traceback()tracemalloc_get_traces_table()reentrant_keytracemalloc_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: