Description
(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 to PyInterpreterState
(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:
domain | func | wraps | wraps (reentrant) | actually wraps |
---|---|---|---|---|
- |
tracemalloc_alloc() |
<original malloc() or calloc() > |
<--- | |
- |
tracemalloc_realloc() |
<original realloc() or free() > |
<--- | |
- |
tracemalloc_raw_alloc() |
tracemalloc_alloc() * |
<original malloc() or calloc() > |
|
- |
tracemalloc_alloc_gil() |
tracemalloc_alloc() |
<original malloc() or calloc() > |
|
raw | ||||
tracemalloc_raw_malloc() |
tracemalloc_alloc() |
<original malloc() > |
tracemalloc_raw_alloc() |
|
tracemalloc_raw_calloc() |
tracemalloc_alloc() |
<original calloc() > |
tracemalloc_raw_alloc() |
|
tracemalloc_raw_realloc() |
tracemalloc_realloc() * |
<original realloc() > |
||
tracemalloc_free() |
<original free() > |
<--- | ||
mem | ||||
obj | ||||
tracemalloc_malloc_gil() |
tracemalloc_alloc_gil() |
<--- | ||
tracemalloc_calloc_gil() |
tracemalloc_alloc_gil() |
<--- | ||
tracemalloc_realloc_gil() |
tracemalloc_realloc() |
<original realloc() > |
||
tracemalloc_free() |
<original free() > |
<--- |
* Note that tracemalloc_raw_alloc()
wraps the tracemalloc_alloc()
call
with PyGILState_Ensure()
/PyGILState_Release()
.
Likewise for tracemalloc_raw_realloc()
where it calls tracemalloc_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
name | type | protected by | #ifdef | notes |
---|---|---|---|---|
config |
struct _PyTraceMalloc_Config |
|||
. initialized |
enum {} |
GIL | ||
. tracing |
bool |
GIL | ||
. max_nframe |
int |
GIL | ||
allocators |
see PEP 445 (docs) | |||
. mem |
PyMemAllocatorEx |
GIL | ||
. raw |
PyMemAllocatorEx |
GIL | ||
. obj |
PyMemAllocatorEx |
GIL | ||
tables_lock |
PyThread_type_lock |
GIL | TRACE_RAW_MALLOC |
|
traced_memory |
size_t |
tables_lock |
||
peak_traced_memory |
size_t |
tables_lock |
||
filenames |
_Py_hashtable_t * |
GIL | interned; effectively a set of objects |
|
traceback |
struct tracemalloc_traceback * |
GIL | a temporary buffer | |
tracebacks |
_Py_hashtable_t * |
GIL | interned; effectively a set of traceback_t |
|
traces |
_Py_hashtable_t * |
tables_lock |
void-ptr -> trace_t |
|
domains |
_Py_hashtable_t * |
tables_lock |
domain -> _Py_hashtable_t * (per-domain traces ) |
|
empty_traceback |
struct tracemalloc_traceback |
??? | ||
reentrant_key |
Py_tss_t |
??? |
notes:
- each frame in
struct tracemalloc_traceback
holds a filename object traceback_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:
name | context | get | set |
---|---|---|---|
config |
|||
. initialized |
lifecycle | tracemalloc_init() tracemalloc_deinit() |
tracemalloc_init() tracemalloc_deinit() |
. tracing |
module | _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() |
|
C-API | PyTraceMalloc_Track() PyTraceMalloc_Untrack() _PyTraceMalloc_NewReference() _PyMem_DumpTraceback() |
||
lifecycle | tracemalloc_start() tracemalloc_stop() |
tracemalloc_start() tracemalloc_stop() |
|
internal | tracemalloc_get_traceback() |
||
. max_nframe |
module | _tracemalloc_get_traceback_limit_impl() |
|
lifecycle | tracemalloc_start() |
||
internal | traceback_get_frames() |
||
allocators |
|||
. mem |
lifecycle | tracemalloc_start() +tracemalloc_stop() |
|
. raw |
lifecycle | tracemalloc_init() +tracemalloc_start() +tracemalloc_stop() |
|
internal | raw_malloc() raw_free() |
||
. obj |
lifecycle | tracemalloc_start() +tracemalloc_stop() |
|
tables_lock |
module | _tracemalloc__get_traces_impl() +_tracemalloc_get_tracemalloc_memory_impl() +_tracemalloc_get_traced_memory_impl() +_tracemalloc_reset_peak_impl() + |
|
C-API | PyTraceMalloc_Track() +PyTraceMalloc_Untrack() +_PyTraceMalloc_NewReference() + |
||
lifecycle | tracemalloc_init() tracemalloc_deinit() |
tracemalloc_init() *tracemalloc_deinit() * |
|
allocator | tracemalloc_alloc() +tracemalloc_realloc() +tracemalloc_free() +tracemalloc_realloc_gil() +tracemalloc_raw_realloc() + |
||
internal | tracemalloc_get_traceback() +tracemalloc_clear_traces() + |
||
traced_memory |
module | _tracemalloc_get_traced_memory_impl() _tracemalloc_reset_peak_impl() |
|
internal | tracemalloc_add_trace() |
tracemalloc_add_trace() tracemalloc_remove_trace() tracemalloc_clear_traces() |
|
peak_traced_memory |
module | _tracemalloc_get_traced_memory_impl() |
_tracemalloc_reset_peak_impl() |
internal | tracemalloc_add_trace() |
tracemalloc_add_trace() tracemalloc_clear_traces() |
|
filenames |
module | _tracemalloc_get_tracemalloc_memory_impl() |
|
lifecycle | tracemalloc_init() * |
||
internal | tracemalloc_get_frame() tracemalloc_clear_traces() + |
||
traceback |
lifecycle | tracemalloc_stop() |
tracemalloc_start() *tracemalloc_stop() * |
internal | traceback_new() + |
||
tracebacks |
module | _tracemalloc_get_tracemalloc_memory_impl() |
|
lifecycle | tracemalloc_init() *tracemalloc_deinit() + |
||
internal | traceback_new() +tracemalloc_clear_traces() + |
||
traces |
module | _tracemalloc__get_traces_impl() _tracemalloc_get_tracemalloc_memory_impl() |
|
C-API | _PyTraceMalloc_NewReference() |
||
lifecycle | tracemalloc_deinit() + |
tracemalloc_init() * |
|
internal | tracemalloc_get_traces_table() tracemalloc_add_trace() (indirect)tracemalloc_remove_trace() (indirect)tracemalloc_get_traceback() (indirect)tracemalloc_clear_traces() + |
||
domains |
module | _tracemalloc__get_traces_impl() _tracemalloc_get_tracemalloc_memory_impl() |
|
lifecycle | tracemalloc_deinit() + |
tracemalloc_init() * |
|
internal | tracemalloc_get_traces_table() tracemalloc_remove_trace() (indirect)tracemalloc_get_traceback() (indirect)tracemalloc_clear_traces() +tracemalloc_add_trace() + |
||
empty_traceback |
lifecycle | tracemalloc_init() + |
|
internal | traceback_new() |
||
reentrant_key |
lifecycle | tracemalloc_init() +tracemalloc_deinit() + |
|
allocator | tracemalloc_alloc_gil() (indirect) +tracemalloc_realloc_gil() (indirect) +tracemalloc_raw_alloc() (indirect) +tracemalloc_raw_realloc() (indirect) + |
||
internal | get_reentrant() set_reentrant() + |
* the function allocates/deallocates the value (see below)
+ the function mutates the value (see below)
simple (extraneous):
name | context | allocate/deallocate | get (assert-only) |
---|---|---|---|
config.tracing |
internal | tracemalloc_add_trace() tracemalloc_remove_trace() |
|
tables_lock |
lifecycle | tracemalloc_init() tracemalloc_deinit() |
|
traced_memory |
internal | tracemalloc_remove_trace() |
|
filenames |
lifecycle | tracemalloc_init() |
|
traceback |
lifecycle | tracemalloc_start() tracemalloc_stop() |
tracemalloc_start() |
tracebacks |
lifecycle | tracemalloc_init() |
|
traces |
lifecycle | tracemalloc_init() |
|
domains |
lifecycle | tracemalloc_init() |
mutation of complex fields:
name | context | initialize | finalize | clear | modify |
---|---|---|---|---|---|
allocators.mem |
lifecycle | tracemalloc_start() |
|||
allocators.raw |
lifecycle | tracemalloc_init() tracemalloc_start() |
|||
allocators.obj |
lifecycle | tracemalloc_start() |
|||
tables_lock |
module | _tracemalloc__get_traces_impl() _tracemalloc_get_tracemalloc_memory_impl() _tracemalloc_get_traced_memory_impl() _tracemalloc_reset_peak_impl() |
|||
C-API | PyTraceMalloc_Track() PyTraceMalloc_Untrack() _PyTraceMalloc_NewReference() |
||||
allocator | tracemalloc_alloc() |
tracemalloc_alloc() tracemalloc_realloc() tracemalloc_free() tracemalloc_realloc_gil() tracemalloc_raw_realloc() |
|||
internal | tracemalloc_clear_traces() tracemalloc_get_traceback() |
||||
filenames |
internal | tracemalloc_clear_traces() |
tracemalloc_get_frame() tracemalloc_clear_traces() |
||
lifecycle | tracemalloc_deinit() |
||||
traceback |
internal | traceback_new() |
|||
tracebacks |
lifecycle | tracemalloc_deinit() |
|||
internal | tracemalloc_clear_traces() |
traceback_new() |
|||
traces |
lifecycle | tracemalloc_deinit() |
|||
internal | tracemalloc_clear_traces() |
||||
domains |
lifecycle | tracemalloc_deinit() |
|||
internal | tracemalloc_clear_traces() |
tracemalloc_add_trace() |
|||
reentrant_key |
lifecycle | tracemalloc_init() |
tracemalloc_deinit() |
||
internal | set_reentrant() |
indirection:
name | context | direct | indirect |
---|---|---|---|
allocators.raw |
lifecycle | tracemalloc_start() tracemalloc_copy_trace() |
raw_malloc() |
tracemalloc_stop() |
raw_free() |
||
internal | traceback_new() tracemalloc_add_trace() tracemalloc_copy_trace() |
raw_malloc() |
|
traceback_new() tracemalloc_add_trace() tracemalloc_remove_trace() |
raw_free() |
||
traces |
internal | tracemalloc_add_trace() tracemalloc_remove_trace() tracemalloc_get_traceback() |
tracemalloc_get_traces_table() |
domains |
internal | tracemalloc_add_trace() tracemalloc_remove_trace() tracemalloc_get_traceback() |
tracemalloc_get_traces_table() |
reentrant_key |
allocator | 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
Metadata
Metadata
Assignees
Labels
Projects
Status