8000 bpo-35053: Enhance tracemalloc to trace free lists (GH-10063) · python/cpython@9e00e80 · GitHub
[go: up one dir, main page]

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

Appearance settings

Commit 9e00e80

Browse files
authored
bpo-35053: Enhance tracemalloc to trace free lists (GH-10063)
tracemalloc now tries to update the traceback when an object is reused from a "free list" (optimization for faster object creation, used by the builtin list type for example). Changes: * Add _PyTraceMalloc_NewReference() function which tries to update the Python traceback of a Python object. * _Py_NewReference() now calls _PyTraceMalloc_NewReference(). * Add an unit test.
1 parent d7c3e5f commit 9e00e80

File tree

7 files changed

+157
-51
lines changed

7 files changed

+157
-51
lines changed

Include/object.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -776,6 +776,9 @@ PyAPI_FUNC(void) _Py_AddToAllObjects(PyObject *, int force);
776776
* inline.
777777
*/
778778
#define _Py_NewReference(op) ( \
779+
(_Py_tracemalloc_config.tracing \
780+
? _PyTraceMalloc_NewReference(op) \
781+
: 0), \
779782
_Py_INC_TPALLOCS(op) _Py_COUNT_ALLOCS_COMMA \
780783
_Py_INC_REFTOTAL _Py_REF_DEBUG_COMMA \
781784
Py_REFCNT(op) = 1)

Include/pymem.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ PyAPI_FUNC(int) PyTraceMalloc_Track(
3636
uintptr_t ptr,
3737
size_t size);
3838

39+
/* Update the Python traceback of an object.
40+
This function can be used when a memory block is reused from a free list. */
41+
PyAPI_FUNC(int) _PyTraceMalloc_NewReference(PyObject *op);
42+
3943
/* Untrack an allocated memory block in the tracemalloc module.
4044
Do nothing if the block was not tracked.
4145
@@ -239,6 +243,40 @@ PyAPI_FUNC(int) _PyMem_SetDefaultAllocator(
239243
PyMemAllocatorEx *old_alloc);
240244
#endif
241245

246+
247+
/* bpo-35053: expose _Py_tracemalloc_config for performance:
248+
_Py_NewReference() needs an efficient check to test if tracemalloc is
249+
tracing. */
250+
struct _PyTraceMalloc_Config {
251+
/* Module initialized?
252+
Variable protected by the GIL */
253+
enum {
254+
TRACEMALLOC_NOT_INITIALIZED,
255+
TRACEMALLOC_INITIALIZED,
256+
TRACEMALLOC_FINALIZED
257+
} initialized;
258+
259+
/* Is tracemalloc tracing memory allocations?
260+
Variable protected by the GIL */
261+
int tracing;
262+
263+
/* limit of the number of frames in a traceback, 1 by default.
264+
Variable protected by the GIL. */
265+
int max_nframe;
266+
267+
/* use domain in trace key?
268+
Variable protected by the GIL. */
269+
int use_domain;
270+
};
271+
272+
PyAPI_DATA(struct _PyTraceMalloc_Config) _Py_tracemalloc_config;
273+
274+
#define _PyTraceMalloc_Config_INIT \
275+
{.initialized = TRACEMALLOC_NOT_INITIALIZED, \
276+
.tracing = 0, \
277+
.max_nframe = 1, \
278+
.use_domain = 0}
279+
242280
#ifdef __cplusplus
243281
}
244282
#endif

Lib/test/test_tracemalloc.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,26 @@ def test_get_object_traceback(self):
111111
traceback = tracemalloc.get_object_traceback(obj)
112112
self.assertEqual(traceback, obj_traceback)
113113

114+
def test_new_reference(self):
115+
tracemalloc.clear_traces()
116+
# gc.collect() indirectly calls PyList_ClearFreeList()
117+
support.gc_collect()
118+
119+
# Create a list and "destroy it": put it in the PyListObject free list
120+
obj = []
121+
obj = None
122+
123+
# Create a list which should reuse the previously created empty list
124+
obj = []
125+
126+
nframe = tracemalloc.get_traceback_limit()
127+
frames = get_frames(nframe, -3)
128+
obj_traceback = tracemalloc.Traceback(frames)
129+
130+
traceback = tracemalloc.get_object_traceback(obj)
131+
self.assertIsNotNone(traceback)
132+
self.assertEqual(traceback, obj_traceback)
133+
114134
def test_set_traceback_limit(self):
115135
obj_size = 10
116136

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
tracemalloc now tries to update the traceback when an object is reused from a
2+
"free list" (optimization for faster object creation, used by the builtin list
3+
type for example).

0 commit comments

Comments
 (0)
0