Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Isolate the tracemalloc Module Between Interpreters #101520

Closed
Labels
@ericsnowcurrently

Description

@ericsnowcurrently

(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:

domainfuncwrapswraps (reentrant)actually wraps

-

tracemalloc_alloc()<originalmalloc() orcalloc()><---

-

tracemalloc_realloc()<originalrealloc() orfree()><---

-

tracemalloc_raw_alloc()tracemalloc_alloc()*<originalmalloc() orcalloc()>

-

tracemalloc_alloc_gil()tracemalloc_alloc()<originalmalloc() orcalloc()>
raw
tracemalloc_raw_malloc()tracemalloc_alloc()<originalmalloc()>tracemalloc_raw_alloc()
tracemalloc_raw_calloc()tracemalloc_alloc()<originalcalloc()>tracemalloc_raw_alloc()
tracemalloc_raw_realloc()tracemalloc_realloc()*<originalrealloc()>
tracemalloc_free()<originalfree()><---
mem
obj
tracemalloc_malloc_gil()tracemalloc_alloc_gil()<---
tracemalloc_calloc_gil()tracemalloc_alloc_gil()<---
tracemalloc_realloc_gil()tracemalloc_realloc()<originalrealloc()>
tracemalloc_free()<originalfree()><---

* Note thattracemalloc_raw_alloc() wraps thetracemalloc_alloc() call
withPyGILState_Ensure()/PyGILState_Release().
Likewise fortracemalloc_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

struct
#ifdef__GNUC__
__attribute__((packed))
#endif
tracemalloc_frame {
/* filename cannot be NULL: "<unknown>" is used if the Python frame
filename is NULL */
PyObject*filename;
unsignedintlineno;
};
#ifdef_MSC_VER
#pragma pack(pop)
#endif

structtracemalloc_traceback {
Py_uhash_thash;
/* Number of frames stored */
uint16_tnframe;
/* Total number of frames the traceback had */
uint16_ttotal_nframe;
structtracemalloc_frameframes[1];
};

structtracemalloc_traceback {
Py_uhash_thash;
/* Number of frames stored */
uint16_tnframe;
/* Total number of frames the traceback had */
uint16_ttotal_nframe;
structtracemalloc_frameframes[1];
};
struct_tracemalloc_runtime_state {
struct_PyTraceMalloc_Configconfig;
/* Protected by the GIL */
struct {
PyMemAllocatorExmem;
PyMemAllocatorExraw;
PyMemAllocatorExobj;
}allocators;
#if defined(TRACE_RAW_MALLOC)
PyThread_type_locktables_lock;
#endif
/* Size in bytes of currently traced memory.
Protected by TABLES_LOCK(). */
size_ttraced_memory;
/* Peak size in bytes of traced memory.
Protected by TABLES_LOCK(). */
size_tpeak_traced_memory;
/* Hash table used as a set to intern filenames:
PyObject* => PyObject*.
Protected by the GIL */
_Py_hashtable_t*filenames;
/* Buffer to store a new traceback in traceback_new().
Protected by the GIL. */
structtracemalloc_traceback*traceback;
/* Hash table used as a set to intern tracebacks:
traceback_t* => traceback_t*
Protected by the GIL */
_Py_hashtable_t*tracebacks;
/* pointer (void*) => trace (trace_t*).
Protected by TABLES_LOCK(). */
_Py_hashtable_t*traces;
/* domain (unsigned int) => traces (_Py_hashtable_t).
Protected by TABLES_LOCK(). */
_Py_hashtable_t*domains;
structtracemalloc_tracebackempty_traceback;
Py_tss_treentrant_key;
};

typedefstructtracemalloc_frameframe_t;
typedefstructtracemalloc_tracebacktraceback_t;

/* Trace of a memory block */
typedefstruct {
/* Size of the memory block in bytes */
size_tsize;
/* Traceback where the memory block was allocated */
traceback_t*traceback;
}trace_t;

nametypeprotected by#ifdefnotes
configstruct _PyTraceMalloc_Config
    .initializedenum {}GIL
    .tracingboolGIL
    .max_nframeintGIL
allocatorssee PEP 445 (docs)
    .memPyMemAllocatorExGIL
    .rawPyMemAllocatorExGIL
    .objPyMemAllocatorExGIL
tables_lockPyThread_type_lockGILTRACE_RAW_MALLOC
traced_memorysize_ttables_lock
peak_traced_memorysize_ttables_lock
filenames_Py_hashtable_t *GILinterned; effectively aset of objects
tracebackstruct tracemalloc_traceback *GILa temporary buffer
tracebacks_Py_hashtable_t *GILinterned; effectively aset oftraceback_t
traces_Py_hashtable_t *tables_lockvoid-ptr ->trace_t
domains_Py_hashtable_t *tables_lockdomain ->_Py_hashtable_t * (per-domaintraces)
empty_tracebackstruct tracemalloc_traceback???
reentrant_keyPy_tss_t???

notes:

  • each frame instruct 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:

namecontextgetset
config
    .initializedlifecycletracemalloc_init()
tracemalloc_deinit()
tracemalloc_init()
tracemalloc_deinit()
    .tracingmodule_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-APIPyTraceMalloc_Track()
PyTraceMalloc_Untrack()
_PyTraceMalloc_NewReference()
_PyMem_DumpTraceback()
lifecycletracemalloc_start()
tracemalloc_stop()
tracemalloc_start()
tracemalloc_stop()
internaltracemalloc_get_traceback()
    .max_nframemodule_tracemalloc_get_traceback_limit_impl()
lifecycletracemalloc_start()
internaltraceback_get_frames()
allocators
    .memlifecycletracemalloc_start() +
tracemalloc_stop()
    .rawlifecycletracemalloc_init() +
tracemalloc_start() +
tracemalloc_stop()
internalraw_malloc()
raw_free()
    .objlifecycletracemalloc_start() +
tracemalloc_stop()
tables_lockmodule_tracemalloc__get_traces_impl() +
_tracemalloc_get_tracemalloc_memory_impl() +
_tracemalloc_get_traced_memory_impl() +
_tracemalloc_reset_peak_impl() +
C-APIPyTraceMalloc_Track() +
PyTraceMalloc_Untrack() +
_PyTraceMalloc_NewReference() +
lifecycletracemalloc_init()
tracemalloc_deinit()
tracemalloc_init() *
tracemalloc_deinit() *
allocatortracemalloc_alloc() +
tracemalloc_realloc() +
tracemalloc_free() +
tracemalloc_realloc_gil() +
tracemalloc_raw_realloc() +
internaltracemalloc_get_traceback() +
tracemalloc_clear_traces() +
traced_memorymodule_tracemalloc_get_traced_memory_impl()
_tracemalloc_reset_peak_impl()
internaltracemalloc_add_trace()tracemalloc_add_trace()
tracemalloc_remove_trace()
tracemalloc_clear_traces()
peak_traced_memorymodule_tracemalloc_get_traced_memory_impl()_tracemalloc_reset_peak_impl()
internaltracemalloc_add_trace()tracemalloc_add_trace()
tracemalloc_clear_traces()
filenamesmodule_tracemalloc_get_tracemalloc_memory_impl()
lifecycletracemalloc_init() *
internaltracemalloc_get_frame()
tracemalloc_clear_traces() +
tracebacklifecycletracemalloc_stop()tracemalloc_start() *
tracemalloc_stop() *
internaltraceback_new() +
tracebacksmodule_tracemalloc_get_tracemalloc_memory_impl()
lifecycletracemalloc_init() *
tracemalloc_deinit() +
internaltraceback_new() +
tracemalloc_clear_traces() +
tracesmodule_tracemalloc__get_traces_impl()
_tracemalloc_get_tracemalloc_memory_impl()
C-API_PyTraceMalloc_NewReference()
lifecycletracemalloc_deinit() +tracemalloc_init() *
internaltracemalloc_get_traces_table()
tracemalloc_add_trace() (indirect)
tracemalloc_remove_trace() (indirect)
tracemalloc_get_traceback() (indirect)
tracemalloc_clear_traces() +
domainsmodule_tracemalloc__get_traces_impl()
_tracemalloc_get_tracemalloc_memory_impl()
lifecycletracemalloc_deinit() +tracemalloc_init() *
internaltracemalloc_get_traces_table()
tracemalloc_remove_trace() (indirect)
tracemalloc_get_traceback() (indirect)
tracemalloc_clear_traces() +
tracemalloc_add_trace() +
empty_tracebacklifecycletracemalloc_init() +
internaltraceback_new()
reentrant_keylifecycletracemalloc_init() +
tracemalloc_deinit() +
allocatortracemalloc_alloc_gil() (indirect) +
tracemalloc_realloc_gil() (indirect) +
tracemalloc_raw_alloc() (indirect) +
tracemalloc_raw_realloc() (indirect) +
internalget_reentrant()
set_reentrant() +

* the function allocates/deallocates the value (see below)
+ the function mutates the value (see below)

simple (extraneous):

namecontextallocate/deallocateget (assert-only)
config.tracinginternaltracemalloc_add_trace()
tracemalloc_remove_trace()
tables_locklifecycletracemalloc_init()
tracemalloc_deinit()
traced_memoryinternaltracemalloc_remove_trace()
filenameslifecycletracemalloc_init()
tracebacklifecycletracemalloc_start()
tracemalloc_stop()
tracemalloc_start()
tracebackslifecycletracemalloc_init()
traceslifecycletracemalloc_init()
domainslifecycletracemalloc_init()

mutation of complex fields:

namecontextinitializefinalizeclearmodify
allocators.memlifecycletracemalloc_start()
allocators.rawlifecycletracemalloc_init()
tracemalloc_start()
allocators.objlifecycletracemalloc_start()
tables_lockmodule_tracemalloc__get_traces_impl()
_tracemalloc_get_tracemalloc_memory_impl()
_tracemalloc_get_traced_memory_impl()
_tracemalloc_reset_peak_impl()
C-APIPyTraceMalloc_Track()
PyTraceMalloc_Untrack()
_PyTraceMalloc_NewReference()
allocatortracemalloc_alloc()tracemalloc_alloc()
tracemalloc_realloc()
tracemalloc_free()
tracemalloc_realloc_gil()
tracemalloc_raw_realloc()
internaltracemalloc_clear_traces()
tracemalloc_get_traceback()
filenamesinternaltracemalloc_clear_traces()tracemalloc_get_frame()
tracemalloc_clear_traces()
lifecycletracemalloc_deinit()
tracebackinternaltraceback_new()
tracebackslifecycletracemalloc_deinit()
internaltracemalloc_clear_traces()traceback_new()
traceslifecycletracemalloc_deinit()
internaltracemalloc_clear_traces()
domainslifecycletracemalloc_deinit()
internaltracemalloc_clear_traces()tracemalloc_add_trace()
reentrant_keylifecycletracemalloc_init()tracemalloc_deinit()
internalset_reentrant()

indirection:

namecontextdirectindirect
allocators.rawlifecycletracemalloc_start()
tracemalloc_copy_trace()
raw_malloc()
tracemalloc_stop()raw_free()
internaltraceback_new()
tracemalloc_add_trace()
tracemalloc_copy_trace()
raw_malloc()
traceback_new()
tracemalloc_add_trace()
tracemalloc_remove_trace()
raw_free()
tracesinternaltracemalloc_add_trace()
tracemalloc_remove_trace()
tracemalloc_get_traceback()
tracemalloc_get_traces_table()
domainsinternaltracemalloc_add_trace()
tracemalloc_remove_trace()
tracemalloc_get_traceback()
tracemalloc_get_traces_table()
reentrant_keyallocatortracemalloc_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

No one assigned

    Labels

    Projects

    Status

    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions


      [8]ページ先頭

      ©2009-2025 Movatter.jp