Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
b5ecaf55
Commit
b5ecaf55
authored
Jun 22, 2012
by
David Malcolm
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Issue #14785: Add sys._debugmallocstats() to help debug low-level memory allocation issues
parent
263bd6fe
Changes
24
Hide whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
217 additions
and
35 deletions
+217
-35
Doc/library/sys.rst
Doc/library/sys.rst
+16
-0
Include/dictobject.h
Include/dictobject.h
+1
-0
Include/floatobject.h
Include/floatobject.h
+2
-0
Include/frameobject.h
Include/frameobject.h
+2
-0
Include/listobject.h
Include/listobject.h
+1
-0
Include/methodobject.h
Include/methodobject.h
+5
-0
Include/object.h
Include/object.h
+8
-0
Include/objimpl.h
Include/objimpl.h
+3
-1
Include/setobject.h
Include/setobject.h
+1
-0
Include/tupleobject.h
Include/tupleobject.h
+3
-0
Lib/test/test_sys.py
Lib/test/test_sys.py
+6
-0
Misc/NEWS
Misc/NEWS
+3
-0
Objects/classobject.c
Objects/classobject.c
+9
-0
Objects/dictobject.c
Objects/dictobject.c
+9
-0
Objects/floatobject.c
Objects/floatobject.c
+10
-0
Objects/frameobject.c
Objects/frameobject.c
+10
-0
Objects/listobject.c
Objects/listobject.c
+9
-0
Objects/methodobject.c
Objects/methodobject.c
+9
-0
Objects/object.c
Objects/object.c
+12
-0
Objects/obmalloc.c
Objects/obmalloc.c
+48
-33
Objects/setobject.c
Objects/setobject.c
+10
-0
Objects/tupleobject.c
Objects/tupleobject.c
+16
-0
Python/pythonrun.c
Python/pythonrun.c
+1
-1
Python/sysmodule.c
Python/sysmodule.c
+23
-0
No files found.
Doc/library/sys.rst
View file @
b5ecaf55
...
...
@@ -106,6 +106,22 @@ always available.
This function should be used for internal and specialized purposes only.
.. function:: _debugmallocstats()
Print low-level information to stderr about the state of CPython's memory
allocator.
If Python is configured --with-pydebug, it also performs some expensive
internal consistency checks.
.. versionadded:: 3.3
.. impl-detail::
This function is specific to CPython. The exact output format is not
defined here, and may change.
.. data:: dllhandle
Integer specifying the handle of the Python DLL. Availability: Windows.
...
...
Include/dictobject.h
View file @
b5ecaf55
...
...
@@ -111,6 +111,7 @@ PyAPI_FUNC(int) PyDict_DelItemString(PyObject *dp, const char *key);
#ifndef Py_LIMITED_API
int
_PyObjectDict_SetItem
(
PyTypeObject
*
tp
,
PyObject
**
dictptr
,
PyObject
*
name
,
PyObject
*
value
);
PyObject
*
_PyDict_LoadGlobal
(
PyDictObject
*
,
PyDictObject
*
,
PyObject
*
);
PyAPI_FUNC
(
void
)
_PyDict_DebugMallocStats
(
FILE
*
out
);
#endif
#ifdef __cplusplus
...
...
Include/floatobject.h
View file @
b5ecaf55
...
...
@@ -110,6 +110,8 @@ PyAPI_FUNC(double) _PyFloat_Unpack8(const unsigned char *p, int le);
/* free list api */
PyAPI_FUNC
(
int
)
PyFloat_ClearFreeList
(
void
);
PyAPI_FUNC
(
void
)
_PyFloat_DebugMallocStats
(
FILE
*
out
);
/* Format the object based on the format_spec, as defined in PEP 3101
(Advanced String Formatting). */
PyAPI_FUNC
(
int
)
_PyFloat_FormatAdvancedWriter
(
...
...
Include/frameobject.h
View file @
b5ecaf55
...
...
@@ -79,6 +79,8 @@ PyAPI_FUNC(void) PyFrame_FastToLocals(PyFrameObject *);
PyAPI_FUNC
(
int
)
PyFrame_ClearFreeList
(
void
);
PyAPI_FUNC
(
void
)
_PyFrame_DebugMallocStats
(
FILE
*
out
);
/* Return the line of code the frame is currently executing. */
PyAPI_FUNC
(
int
)
PyFrame_GetLineNumber
(
PyFrameObject
*
);
...
...
Include/listobject.h
View file @
b5ecaf55
...
...
@@ -64,6 +64,7 @@ PyAPI_FUNC(PyObject *) PyList_AsTuple(PyObject *);
PyAPI_FUNC
(
PyObject
*
)
_PyList_Extend
(
PyListObject
*
,
PyObject
*
);
PyAPI_FUNC
(
int
)
PyList_ClearFreeList
(
void
);
PyAPI_FUNC
(
void
)
_PyList_DebugMallocStats
(
FILE
*
out
);
#endif
/* Macro, trading safety for speed */
...
...
Include/methodobject.h
View file @
b5ecaf55
...
...
@@ -82,6 +82,11 @@ typedef struct {
PyAPI_FUNC
(
int
)
PyCFunction_ClearFreeList
(
void
);
#ifndef Py_LIMITED_API
PyAPI_FUNC
(
void
)
_PyCFunction_DebugMallocStats
(
FILE
*
out
);
PyAPI_FUNC
(
void
)
_PyMethod_DebugMallocStats
(
FILE
*
out
);
#endif
#ifdef __cplusplus
}
#endif
...
...
Include/object.h
View file @
b5ecaf55
...
...
@@ -977,6 +977,14 @@ PyAPI_DATA(PyObject *) _PyTrash_delete_later;
else \
_PyTrash_deposit_object((PyObject*)op);
#ifndef Py_LIMITED_API
PyAPI_FUNC
(
void
)
_PyDebugAllocatorStats
(
FILE
*
out
,
const
char
*
block_name
,
int
num_blocks
,
size_t
sizeof_block
);
PyAPI_FUNC
(
void
)
_PyObject_DebugTypeStats
(
FILE
*
out
);
#endif
/* ifndef Py_LIMITED_API */
#ifdef __cplusplus
}
#endif
...
...
Include/objimpl.h
View file @
b5ecaf55
...
...
@@ -101,13 +101,15 @@ PyAPI_FUNC(void) PyObject_Free(void *);
/* Macros */
#ifdef WITH_PYMALLOC
#ifndef Py_LIMITED_API
PyAPI_FUNC
(
void
)
_PyObject_DebugMallocStats
(
FILE
*
out
);
#endif
/* #ifndef Py_LIMITED_API */
#ifdef PYMALLOC_DEBUG
/* WITH_PYMALLOC && PYMALLOC_DEBUG */
PyAPI_FUNC
(
void
*
)
_PyObject_DebugMalloc
(
size_t
nbytes
);
PyAPI_FUNC
(
void
*
)
_PyObject_DebugRealloc
(
void
*
p
,
size_t
nbytes
);
PyAPI_FUNC
(
void
)
_PyObject_DebugFree
(
void
*
p
);
PyAPI_FUNC
(
void
)
_PyObject_DebugDumpAddress
(
const
void
*
p
);
PyAPI_FUNC
(
void
)
_PyObject_DebugCheckAddress
(
const
void
*
p
);
PyAPI_FUNC
(
void
)
_PyObject_DebugMallocStats
(
void
);
PyAPI_FUNC
(
void
*
)
_PyObject_DebugMallocApi
(
char
api
,
size_t
nbytes
);
PyAPI_FUNC
(
void
*
)
_PyObject_DebugReallocApi
(
char
api
,
void
*
p
,
size_t
nbytes
);
PyAPI_FUNC
(
void
)
_PyObject_DebugFreeApi
(
char
api
,
void
*
p
);
...
...
Include/setobject.h
View file @
b5ecaf55
...
...
@@ -101,6 +101,7 @@ PyAPI_FUNC(PyObject *) PySet_Pop(PyObject *set);
PyAPI_FUNC
(
int
)
_PySet_Update
(
PyObject
*
set
,
PyObject
*
iterable
);
PyAPI_FUNC
(
int
)
PySet_ClearFreeList
(
void
);
PyAPI_FUNC
(
void
)
_PySet_DebugMallocStats
(
FILE
*
out
);
#endif
#ifdef __cplusplus
...
...
Include/tupleobject.h
View file @
b5ecaf55
...
...
@@ -63,6 +63,9 @@ PyAPI_FUNC(void) _PyTuple_MaybeUntrack(PyObject *);
#endif
PyAPI_FUNC
(
int
)
PyTuple_ClearFreeList
(
void
);
#ifndef Py_LIMITED_API
PyAPI_FUNC
(
void
)
_PyTuple_DebugMallocStats
(
FILE
*
out
);
#endif
/* Py_LIMITED_API */
#ifdef __cplusplus
}
...
...
Lib/test/test_sys.py
View file @
b5ecaf55
...
...
@@ -603,6 +603,12 @@ class SysModuleTest(unittest.TestCase):
self
.
assertEqual
(
sys
.
implementation
.
name
,
sys
.
implementation
.
name
.
lower
())
def
test_debugmallocstats
(
self
):
# Test sys._debugmallocstats()
from
test.script_helper
import
assert_python_ok
args
=
[
'-c'
,
'import sys; sys._debugmallocstats()'
]
ret
,
out
,
err
=
assert_python_ok
(
*
args
)
self
.
assertIn
(
b"free PyDictObjects"
,
err
)
class
SizeofTest
(
unittest
.
TestCase
):
...
...
Misc/NEWS
View file @
b5ecaf55
...
...
@@ -147,6 +147,9 @@ Library
-
Issue
#
14963
:
Convert
contextlib
.
ExitStack
.
__exit__
to
use
an
iterative
algorithm
(
Patch
by
Alon
Horev
)
-
Issue
#
14785
:
Add
sys
.
_debugmallocstats
()
to
help
debug
low
-
level
memory
allocation
issues
C
-
API
-----
...
...
Objects/classobject.c
View file @
b5ecaf55
...
...
@@ -400,6 +400,15 @@ PyMethod_Fini(void)
(
void
)
PyMethod_ClearFreeList
();
}
/* Print summary info about the state of the optimized allocator */
void
_PyMethod_DebugMallocStats
(
FILE
*
out
)
{
_PyDebugAllocatorStats
(
out
,
"free PyMethodObject"
,
numfree
,
sizeof
(
PyMethodObject
));
}
/* ------------------------------------------------------------------------
* instance method
*/
...
...
Objects/dictobject.c
View file @
b5ecaf55
...
...
@@ -255,6 +255,15 @@ PyDict_ClearFreeList(void)
return
ret
;
}
/* Print summary info about the state of the optimized allocator */
void
_PyDict_DebugMallocStats
(
FILE
*
out
)
{
_PyDebugAllocatorStats
(
out
,
"free PyDictObject"
,
numfree
,
sizeof
(
PyDictObject
));
}
void
PyDict_Fini
(
void
)
{
...
...
Objects/floatobject.c
View file @
b5ecaf55
...
...
@@ -1933,6 +1933,16 @@ PyFloat_Fini(void)
(
void
)
PyFloat_ClearFreeList
();
}
/* Print summary info about the state of the optimized allocator */
void
_PyFloat_DebugMallocStats
(
FILE
*
out
)
{
_PyDebugAllocatorStats
(
out
,
"free PyFloatObject"
,
numfree
,
sizeof
(
PyFloatObject
));
}
/*----------------------------------------------------------------------------
* _PyFloat_{Pack,Unpack}{4,8}. See floatobject.h.
*/
...
...
Objects/frameobject.c
View file @
b5ecaf55
...
...
@@ -955,3 +955,13 @@ PyFrame_Fini(void)
Py_XDECREF
(
builtin_object
);
builtin_object
=
NULL
;
}
/* Print summary info about the state of the optimized allocator */
void
_PyFrame_DebugMallocStats
(
FILE
*
out
)
{
_PyDebugAllocatorStats
(
out
,
"free PyFrameObject"
,
numfree
,
sizeof
(
PyFrameObject
));
}
Objects/listobject.c
View file @
b5ecaf55
...
...
@@ -117,6 +117,15 @@ PyList_Fini(void)
PyList_ClearFreeList
();
}
/* Print summary info about the state of the optimized allocator */
void
_PyList_DebugMallocStats
(
FILE
*
out
)
{
_PyDebugAllocatorStats
(
out
,
"free PyListObject"
,
numfree
,
sizeof
(
PyListObject
));
}
PyObject
*
PyList_New
(
Py_ssize_t
size
)
{
...
...
Objects/methodobject.c
View file @
b5ecaf55
...
...
@@ -338,6 +338,15 @@ PyCFunction_Fini(void)
(
void
)
PyCFunction_ClearFreeList
();
}
/* Print summary info about the state of the optimized allocator */
void
_PyCFunction_DebugMallocStats
(
FILE
*
out
)
{
_PyDebugAllocatorStats
(
out
,
"free PyCFunction"
,
numfree
,
sizeof
(
PyCFunction
));
}
/* PyCFunction_New() is now just a macro that calls PyCFunction_NewEx(),
but it's part of the API so we need to keep a function around that
existing C extensions can call.
...
...
Objects/object.c
View file @
b5ecaf55
...
...
@@ -1852,6 +1852,18 @@ PyMem_Free(void *p)
PyMem_FREE
(
p
);
}
void
_PyObject_DebugTypeStats
(
FILE
*
out
)
{
_PyCFunction_DebugMallocStats
(
out
);
_PyDict_DebugMallocStats
(
out
);
_PyFloat_DebugMallocStats
(
out
);
_PyFrame_DebugMallocStats
(
out
);
_PyList_DebugMallocStats
(
out
);
_PyMethod_DebugMallocStats
(
out
);
_PySet_DebugMallocStats
(
out
);
_PyTuple_DebugMallocStats
(
out
);
}
/* These methods are used to control infinite recursion in repr, str, print,
etc. Container objects that may recursively contain themselves,
...
...
Objects/obmalloc.c
View file @
b5ecaf55
...
...
@@ -523,12 +523,10 @@ static struct arena_object* usable_arenas = NULL;
/* Number of arenas allocated that haven't been free()'d. */
static
size_t
narenas_currently_allocated
=
0
;
#ifdef PYMALLOC_DEBUG
/* Total number of times malloc() called to allocate an arena. */
static
size_t
ntimes_arena_allocated
=
0
;
/* High water mark (max value ever seen) for narenas_currently_allocated. */
static
size_t
narenas_highwater
=
0
;
#endif
/* Allocate a new arena. If we run out of memory, return NULL. Else
* allocate a new arena, and return the address of an arena_object
...
...
@@ -545,7 +543,7 @@ new_arena(void)
#ifdef PYMALLOC_DEBUG
if
(
Py_GETENV
(
"PYTHONMALLOCSTATS"
))
_PyObject_DebugMallocStats
();
_PyObject_DebugMallocStats
(
stderr
);
#endif
if
(
unused_arena_objects
==
NULL
)
{
uint
i
;
...
...
@@ -613,11 +611,9 @@ new_arena(void)
arenaobj
->
address
=
(
uptr
)
address
;
++
narenas_currently_allocated
;
#ifdef PYMALLOC_DEBUG
++
ntimes_arena_allocated
;
if
(
narenas_currently_allocated
>
narenas_highwater
)
narenas_highwater
=
narenas_currently_allocated
;
#endif
arenaobj
->
freepools
=
NULL
;
/* pool_address <- first pool-aligned address in the arena
nfreepools <- number of whole pools that fit after alignment */
...
...
@@ -1723,17 +1719,19 @@ _PyObject_DebugDumpAddress(const void *p)
}
}
#endif
/* PYMALLOC_DEBUG */
static
size_t
printone
(
const
char
*
msg
,
size_t
value
)
printone
(
FILE
*
out
,
const
char
*
msg
,
size_t
value
)
{
int
i
,
k
;
char
buf
[
100
];
size_t
origvalue
=
value
;
fputs
(
msg
,
stderr
);
fputs
(
msg
,
out
);
for
(
i
=
(
int
)
strlen
(
msg
);
i
<
35
;
++
i
)
fputc
(
' '
,
stderr
);
fputc
(
'='
,
stderr
);
fputc
(
' '
,
out
);
fputc
(
'='
,
out
);
/* Write the value with commas. */
i
=
22
;
...
...
@@ -1754,17 +1752,33 @@ printone(const char* msg, size_t value)
while
(
i
>=
0
)
buf
[
i
--
]
=
' '
;
fputs
(
buf
,
stderr
);
fputs
(
buf
,
out
);
return
origvalue
;
}
/* Print summary info to stderr about the state of pymalloc's structures.
void
_PyDebugAllocatorStats
(
FILE
*
out
,
const
char
*
block_name
,
int
num_blocks
,
size_t
sizeof_block
)
{
char
buf1
[
128
];
char
buf2
[
128
];
PyOS_snprintf
(
buf1
,
sizeof
(
buf1
),
"%d %ss * %zd bytes each"
,
num_blocks
,
block_name
,
sizeof_block
);
PyOS_snprintf
(
buf2
,
sizeof
(
buf2
),
"%48s "
,
buf1
);
(
void
)
printone
(
out
,
buf2
,
num_blocks
*
sizeof_block
);
}
#ifdef WITH_PYMALLOC
/* Print summary info to "out" about the state of pymalloc's structures.
* In Py_DEBUG mode, also perform some expensive internal consistency
* checks.
*/
void
_PyObject_DebugMallocStats
(
void
)
_PyObject_DebugMallocStats
(
FILE
*
out
)
{
uint
i
;
const
uint
numclasses
=
SMALL_REQUEST_THRESHOLD
>>
ALIGNMENT_SHIFT
;
...
...
@@ -1793,7 +1807,7 @@ _PyObject_DebugMallocStats(void)
size_t
total
;
char
buf
[
128
];
fprintf
(
stderr
,
"Small block threshold = %d, in %u size classes.
\n
"
,
fprintf
(
out
,
"Small block threshold = %d, in %u size classes.
\n
"
,
SMALL_REQUEST_THRESHOLD
,
numclasses
);
for
(
i
=
0
;
i
<
numclasses
;
++
i
)
...
...
@@ -1847,10 +1861,10 @@ _PyObject_DebugMallocStats(void)
}
assert
(
narenas
==
narenas_currently_allocated
);
fputc
(
'\n'
,
stderr
);
fputc
(
'\n'
,
out
);
fputs
(
"class size num pools blocks in use avail blocks
\n
"
"----- ---- --------- ------------- ------------
\n
"
,
stderr
);
out
);
for
(
i
=
0
;
i
<
numclasses
;
++
i
)
{
size_t
p
=
numpools
[
i
];
...
...
@@ -1861,7 +1875,7 @@ _PyObject_DebugMallocStats(void)
assert
(
b
==
0
&&
f
==
0
);
continue
;
}
fprintf
(
stderr
,
"%5u %6u "
fprintf
(
out
,
"%5u %6u "
"%11"
PY_FORMAT_SIZE_T
"u "
"%15"
PY_FORMAT_SIZE_T
"u "
"%13"
PY_FORMAT_SIZE_T
"u
\n
"
,
...
...
@@ -1871,35 +1885,36 @@ _PyObject_DebugMallocStats(void)
pool_header_bytes
+=
p
*
POOL_OVERHEAD
;
quantization
+=
p
*
((
POOL_SIZE
-
POOL_OVERHEAD
)
%
size
);
}
fputc
(
'\n'
,
stderr
);
(
void
)
printone
(
"# times object malloc called"
,
serialno
);
(
void
)
printone
(
"# arenas allocated total"
,
ntimes_arena_allocated
);
(
void
)
printone
(
"# arenas reclaimed"
,
ntimes_arena_allocated
-
narenas
);
(
void
)
printone
(
"# arenas highwater mark"
,
narenas_highwater
);
(
void
)
printone
(
"# arenas allocated current"
,
narenas
);
fputc
(
'\n'
,
out
);
#ifdef PYMALLOC_DEBUG
(
void
)
printone
(
out
,
"# times object malloc called"
,
serialno
);
#endif
(
void
)
printone
(
out
,
"# arenas allocated total"
,
ntimes_arena_allocated
);
(
void
)
printone
(
out
,
"# arenas reclaimed"
,
ntimes_arena_allocated
-
narenas
);
(
void
)
printone
(
out
,
"# arenas highwater mark"
,
narenas_highwater
);
(
void
)
printone
(
out
,
"# arenas allocated current"
,
narenas
);
PyOS_snprintf
(
buf
,
sizeof
(
buf
),
"%"
PY_FORMAT_SIZE_T
"u arenas * %d bytes/arena"
,
narenas
,
ARENA_SIZE
);
(
void
)
printone
(
buf
,
narenas
*
ARENA_SIZE
);
(
void
)
printone
(
out
,
buf
,
narenas
*
ARENA_SIZE
);
fputc
(
'\n'
,
stderr
);
fputc
(
'\n'
,
out
);
total
=
printone
(
"# bytes in allocated blocks"
,
allocated_bytes
);
total
+=
printone
(
"# bytes in available blocks"
,
available_bytes
);
total
=
printone
(
out
,
"# bytes in allocated blocks"
,
allocated_bytes
);
total
+=
printone
(
out
,
"# bytes in available blocks"
,
available_bytes
);
PyOS_snprintf
(
buf
,
sizeof
(
buf
),
"%u unused pools * %d bytes"
,
numfreepools
,
POOL_SIZE
);
total
+=
printone
(
buf
,
(
size_t
)
numfreepools
*
POOL_SIZE
);
total
+=
printone
(
out
,
buf
,
(
size_t
)
numfreepools
*
POOL_SIZE
);
total
+=
printone
(
"# bytes lost to pool headers"
,
pool_header_bytes
);
total
+=
printone
(
"# bytes lost to quantization"
,
quantization
);
total
+=
printone
(
"# bytes lost to arena alignment"
,
arena_alignment
);
(
void
)
printone
(
"Total"
,
total
);
total
+=
printone
(
out
,
"# bytes lost to pool headers"
,
pool_header_bytes
);
total
+=
printone
(
out
,
"# bytes lost to quantization"
,
quantization
);
total
+=
printone
(
out
,
"# bytes lost to arena alignment"
,
arena_alignment
);
(
void
)
printone
(
out
,
"Total"
,
total
);
}
#endif
/* PYMALLOC_DEBUG
*/
#endif
/* #ifdef WITH_PYMALLOC
*/
#ifdef Py_USING_MEMORY_DEBUGGER
/* Make this function last so gcc won't inline it since the definition is
...
...
Objects/setobject.c
View file @
b5ecaf55
...
...
@@ -1133,6 +1133,16 @@ PySet_Fini(void)
Py_CLEAR
(
emptyfrozenset
);
}
/* Print summary info about the state of the optimized allocator */
void
_PySet_DebugMallocStats
(
FILE
*
out
)
{
_PyDebugAllocatorStats
(
out
,
"free PySetObject"
,
numfree
,
sizeof
(
PySetObject
));
}
static
PyObject
*
set_new
(
PyTypeObject
*
type
,
PyObject
*
args
,
PyObject
*
kwds
)
{
...
...
Objects/tupleobject.c
View file @
b5ecaf55
...
...
@@ -45,6 +45,22 @@ show_track(void)
}
#endif
/* Print summary info about the state of the optimized allocator */
void
_PyTuple_DebugMallocStats
(
FILE
*
out
)
{
#if PyTuple_MAXSAVESIZE > 0
int
i
;
char
buf
[
128
];
for
(
i
=
1
;
i
<
PyTuple_MAXSAVESIZE
;
i
++
)
{
PyOS_snprintf
(
buf
,
sizeof
(
buf
),
"free %d-sized PyTupleObject"
,
i
);
_PyDebugAllocatorStats
(
out
,
buf
,
numfree
[
i
],
_PyObject_VAR_SIZE
(
&
PyTuple_Type
,
i
));
}
#endif
}
PyObject
*
PyTuple_New
(
register
Py_ssize_t
size
)
...
...
Python/pythonrun.c
View file @
b5ecaf55
...
...
@@ -642,7 +642,7 @@ Py_Finalize(void)
#endif
/* Py_TRACE_REFS */
#ifdef PYMALLOC_DEBUG
if
(
Py_GETENV
(
"PYTHONMALLOCSTATS"
))
_PyObject_DebugMallocStats
();
_PyObject_DebugMallocStats
(
stderr
);
#endif
call_ll_exitfuncs
();
...
...
Python/sysmodule.c
View file @
b5ecaf55
...
...
@@ -997,6 +997,27 @@ a 11-tuple where the entries in the tuple are counts of:\n\
extern
"C"
{
#endif
static
PyObject
*
sys_debugmallocstats
(
PyObject
*
self
,
PyObject
*
args
)
{
#ifdef WITH_PYMALLOC
_PyObject_DebugMallocStats
(
stderr
);
fputc
(
'\n'
,
stderr
);
#endif
_PyObject_DebugTypeStats
(
stderr
);
Py_RETURN_NONE
;
}
PyDoc_STRVAR
(
debugmallocstats_doc
,
"_debugmallocstats()
\n
\
\n
\
Print summary info to stderr about the state of
\n
\
pymalloc's structures.
\n
\
\n
\
In Py_DEBUG mode, also perform some expensive internal consistency
\n
\
checks.
\n
\
"
);
#ifdef Py_TRACE_REFS
/* Defined in objects.c because it uses static globals if that file */
extern
PyObject
*
_Py_GetObjects
(
PyObject
*
,
PyObject
*
);
...
...
@@ -1093,6 +1114,8 @@ static PyMethodDef sys_methods[] = {
{
"settrace"
,
sys_settrace
,
METH_O
,
settrace_doc
},
{
"gettrace"
,
sys_gettrace
,
METH_NOARGS
,
gettrace_doc
},
{
"call_tracing"
,
sys_call_tracing
,
METH_VARARGS
,
call_tracing_doc
},
{
"_debugmallocstats"
,
sys_debugmallocstats
,
METH_VARARGS
,
debugmallocstats_doc
},
{
NULL
,
NULL
}
/* sentinel */
};
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment