Kaydet (Commit) 5ea4c067 authored tarafından Victor Stinner's avatar Victor Stinner Kaydeden (comit) GitHub

bpo-30054: Expose tracemalloc C API (#1236)

* Make PyTraceMalloc_Track() and PyTraceMalloc_Untrack() functions
  public (remove the "_" prefix)
* Remove the _PyTraceMalloc_domain_t type: use directly unsigned
  int.
* Document methods

Note: methods are already tested in test_tracemalloc.
üst 26cb4657
...@@ -429,6 +429,28 @@ Customize pymalloc Arena Allocator ...@@ -429,6 +429,28 @@ Customize pymalloc Arena Allocator
Set the arena allocator. Set the arena allocator.
tracemalloc C API
=================
.. versionadded:: 3.7
.. c:function: int PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr, size_t size)
Track an allocated memory block in the :mod:`tracemalloc` module.
Return 0 on success, return ``-1`` on error (failed to allocate memory to
store the trace). Return ``-2`` if tracemalloc is disabled.
If memory block is already tracked, update the existing trace.
.. c:function: int PyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr)
Untrack an allocated memory block in the :mod:`tracemalloc` module.
Do nothing if the block was not tracked.
Return ``-2`` if tracemalloc is disabled, otherwise return ``0``.
.. _memoryexamples: .. _memoryexamples:
Examples Examples
......
...@@ -412,6 +412,9 @@ Filter ...@@ -412,6 +412,9 @@ Filter
Address space of a memory block (``int`` or ``None``). Address space of a memory block (``int`` or ``None``).
tracemalloc uses the domain ``0`` to trace memory allocations made by
Python. C extensions can use other domains to trace other resources.
.. attribute:: inclusive .. attribute:: inclusive
If *inclusive* is ``True`` (include), only match memory blocks allocated If *inclusive* is ``True`` (include), only match memory blocks allocated
...@@ -622,6 +625,16 @@ Trace ...@@ -622,6 +625,16 @@ Trace
The :attr:`Snapshot.traces` attribute is a sequence of :class:`Trace` The :attr:`Snapshot.traces` attribute is a sequence of :class:`Trace`
instances. instances.
.. versionchanged:: 3.6
Added the :attr:`domain` attribute.
.. attribute:: domain
Address space of a memory block (``int``). Read-only property.
tracemalloc uses the domain ``0`` to trace memory allocations made by
Python. C extensions can use other domains to trace other resources.
.. attribute:: size .. attribute:: size
Size of the memory block in bytes (``int``). Size of the memory block in bytes (``int``).
......
...@@ -25,9 +25,6 @@ PyAPI_FUNC(int) _PyMem_SetupAllocators(const char *opt); ...@@ -25,9 +25,6 @@ PyAPI_FUNC(int) _PyMem_SetupAllocators(const char *opt);
PyAPI_FUNC(int) _PyMem_PymallocEnabled(void); PyAPI_FUNC(int) _PyMem_PymallocEnabled(void);
#endif #endif
/* Identifier of an address space (domain) in tracemalloc */
typedef unsigned int _PyTraceMalloc_domain_t;
/* Track an allocated memory block in the tracemalloc module. /* Track an allocated memory block in the tracemalloc module.
Return 0 on success, return -1 on error (failed to allocate memory to store Return 0 on success, return -1 on error (failed to allocate memory to store
the trace). the trace).
...@@ -35,8 +32,8 @@ typedef unsigned int _PyTraceMalloc_domain_t; ...@@ -35,8 +32,8 @@ typedef unsigned int _PyTraceMalloc_domain_t;
Return -2 if tracemalloc is disabled. Return -2 if tracemalloc is disabled.
If memory block is already tracked, update the existing trace. */ If memory block is already tracked, update the existing trace. */
PyAPI_FUNC(int) _PyTraceMalloc_Track( PyAPI_FUNC(int) PyTraceMalloc_Track(
_PyTraceMalloc_domain_t domain, unsigned int domain,
uintptr_t ptr, uintptr_t ptr,
size_t size); size_t size);
...@@ -44,8 +41,8 @@ PyAPI_FUNC(int) _PyTraceMalloc_Track( ...@@ -44,8 +41,8 @@ PyAPI_FUNC(int) _PyTraceMalloc_Track(
Do nothing if the block was not tracked. Do nothing if the block was not tracked.
Return -2 if tracemalloc is disabled, otherwise return 0. */ Return -2 if tracemalloc is disabled, otherwise return 0. */
PyAPI_FUNC(int) _PyTraceMalloc_Untrack( PyAPI_FUNC(int) PyTraceMalloc_Untrack(
_PyTraceMalloc_domain_t domain, unsigned int domain,
uintptr_t ptr); uintptr_t ptr);
/* Get the traceback where a memory block was allocated. /* Get the traceback where a memory block was allocated.
...@@ -57,7 +54,7 @@ PyAPI_FUNC(int) _PyTraceMalloc_Untrack( ...@@ -57,7 +54,7 @@ PyAPI_FUNC(int) _PyTraceMalloc_Untrack(
Raise an exception and return NULL on error. */ Raise an exception and return NULL on error. */
PyAPI_FUNC(PyObject*) _PyTraceMalloc_GetTraceback( PyAPI_FUNC(PyObject*) _PyTraceMalloc_GetTraceback(
_PyTraceMalloc_domain_t domain, unsigned int domain,
uintptr_t ptr); uintptr_t ptr);
#endif /* !Py_LIMITED_API */ #endif /* !Py_LIMITED_API */
......
...@@ -3958,15 +3958,15 @@ tracemalloc_track(PyObject *self, PyObject *args) ...@@ -3958,15 +3958,15 @@ tracemalloc_track(PyObject *self, PyObject *args)
if (release_gil) { if (release_gil) {
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
res = _PyTraceMalloc_Track(domain, (uintptr_t)ptr, size); res = PyTraceMalloc_Track(domain, (uintptr_t)ptr, size);
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
} }
else { else {
res = _PyTraceMalloc_Track(domain, (uintptr_t)ptr, size); res = PyTraceMalloc_Track(domain, (uintptr_t)ptr, size);
} }
if (res < 0) { if (res < 0) {
PyErr_SetString(PyExc_RuntimeError, "_PyTraceMalloc_Track error"); PyErr_SetString(PyExc_RuntimeError, "PyTraceMalloc_Track error");
return NULL; return NULL;
} }
...@@ -3987,9 +3987,9 @@ tracemalloc_untrack(PyObject *self, PyObject *args) ...@@ -3987,9 +3987,9 @@ tracemalloc_untrack(PyObject *self, PyObject *args)
if (PyErr_Occurred()) if (PyErr_Occurred())
return NULL; return NULL;
res = _PyTraceMalloc_Untrack(domain, (uintptr_t)ptr); res = PyTraceMalloc_Untrack(domain, (uintptr_t)ptr);
if (res < 0) { if (res < 0) {
PyErr_SetString(PyExc_RuntimeError, "_PyTraceMalloc_Track error"); PyErr_SetString(PyExc_RuntimeError, "PyTraceMalloc_Untrack error");
return NULL; return NULL;
} }
......
...@@ -74,7 +74,7 @@ __attribute__((packed)) ...@@ -74,7 +74,7 @@ __attribute__((packed))
#endif #endif
{ {
uintptr_t ptr; uintptr_t ptr;
_PyTraceMalloc_domain_t domain; unsigned int domain;
} pointer_t; } pointer_t;
/* Pack the frame_t structure to reduce the memory footprint on 64-bit /* Pack the frame_t structure to reduce the memory footprint on 64-bit
...@@ -578,7 +578,7 @@ tracemalloc_use_domain(void) ...@@ -578,7 +578,7 @@ tracemalloc_use_domain(void)
static void static void
tracemalloc_remove_trace(_PyTraceMalloc_domain_t domain, uintptr_t ptr) tracemalloc_remove_trace(unsigned int domain, uintptr_t ptr)
{ {
trace_t trace; trace_t trace;
int removed; int removed;
...@@ -605,7 +605,7 @@ tracemalloc_remove_trace(_PyTraceMalloc_domain_t domain, uintptr_t ptr) ...@@ -605,7 +605,7 @@ tracemalloc_remove_trace(_PyTraceMalloc_domain_t domain, uintptr_t ptr)
static int static int
tracemalloc_add_trace(_PyTraceMalloc_domain_t domain, uintptr_t ptr, tracemalloc_add_trace(unsigned int domain, uintptr_t ptr,
size_t size) size_t size)
{ {
pointer_t key = {ptr, domain}; pointer_t key = {ptr, domain};
...@@ -1267,7 +1267,7 @@ traceback_to_pyobject(traceback_t *traceback, _Py_hashtable_t *intern_table) ...@@ -1267,7 +1267,7 @@ traceback_to_pyobject(traceback_t *traceback, _Py_hashtable_t *intern_table)
static PyObject* static PyObject*
trace_to_pyobject(_PyTraceMalloc_domain_t domain, trace_t *trace, trace_to_pyobject(unsigned int domain, trace_t *trace,
_Py_hashtable_t *intern_tracebacks) _Py_hashtable_t *intern_tracebacks)
{ {
PyObject *trace_obj = NULL; PyObject *trace_obj = NULL;
...@@ -1313,7 +1313,7 @@ tracemalloc_get_traces_fill(_Py_hashtable_t *traces, _Py_hashtable_entry_t *entr ...@@ -1313,7 +1313,7 @@ tracemalloc_get_traces_fill(_Py_hashtable_t *traces, _Py_hashtable_entry_t *entr
void *user_data) void *user_data)
{ {
get_traces_t *get_traces = user_data; get_traces_t *get_traces = user_data;
_PyTraceMalloc_domain_t domain; unsigned int domain;
trace_t trace; trace_t trace;
PyObject *tracemalloc_obj; PyObject *tracemalloc_obj;
int res; int res;
...@@ -1428,7 +1428,7 @@ finally: ...@@ -1428,7 +1428,7 @@ finally:
static traceback_t* static traceback_t*
tracemalloc_get_traceback(_PyTraceMalloc_domain_t domain, uintptr_t ptr) tracemalloc_get_traceback(unsigned int domain, uintptr_t ptr)
{ {
trace_t trace; trace_t trace;
int found; int found;
...@@ -1783,7 +1783,7 @@ _PyTraceMalloc_Fini(void) ...@@ -1783,7 +1783,7 @@ _PyTraceMalloc_Fini(void)
} }
int int
_PyTraceMalloc_Track(_PyTraceMalloc_domain_t domain, uintptr_t ptr, PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr,
size_t size) size_t size)
{ {
int res; int res;
...@@ -1812,7 +1812,7 @@ _PyTraceMalloc_Track(_PyTraceMalloc_domain_t domain, uintptr_t ptr, ...@@ -1812,7 +1812,7 @@ _PyTraceMalloc_Track(_PyTraceMalloc_domain_t domain, uintptr_t ptr,
int int
_PyTraceMalloc_Untrack(_PyTraceMalloc_domain_t domain, uintptr_t ptr) PyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr)
{ {
if (!tracemalloc_config.tracing) { if (!tracemalloc_config.tracing) {
/* tracemalloc is not tracing: do nothing */ /* tracemalloc is not tracing: do nothing */
...@@ -1828,7 +1828,7 @@ _PyTraceMalloc_Untrack(_PyTraceMalloc_domain_t domain, uintptr_t ptr) ...@@ -1828,7 +1828,7 @@ _PyTraceMalloc_Untrack(_PyTraceMalloc_domain_t domain, uintptr_t ptr)
PyObject* PyObject*
_PyTraceMalloc_GetTraceback(_PyTraceMalloc_domain_t domain, uintptr_t ptr) _PyTraceMalloc_GetTraceback(unsigned int domain, uintptr_t ptr)
{ {
traceback_t *traceback; traceback_t *traceback;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment