@ -39,7 +39,11 @@ static struct {
/* limit of the number of frames in a traceback, 1 by default.
Variable protected by the GIL . */
int max_nframe ;
} tracemalloc_config = { TRACEMALLOC_NOT_INITIALIZED , 0 , 1 } ;
/* use domain in trace key?
Variable protected by the GIL . */
int use_domain ;
} tracemalloc_config = { TRACEMALLOC_NOT_INITIALIZED , 0 , 1 , 1 } ;
# if defined(TRACE_RAW_MALLOC) && defined(WITH_THREAD)
/* This lock is needed because tracemalloc_free() is called without
@ -54,10 +58,23 @@ static PyThread_type_lock tables_lock;
# define TABLES_UNLOCK()
# endif
# define DEFAULT_DOMAIN 0
typedef unsigned int domain_t ;
/* Pack the frame_t structure to reduce the memory footprint. */
typedef struct
# ifdef __GNUC__
__attribute__ ( ( packed ) )
# endif
{
Py_uintptr_t ptr ;
domain_t domain ;
} pointer_t ;
/* Pack the frame_t structure to reduce the memory footprint on 64-bit
architectures : 12 bytes instead of 16. This optimization might produce
SIGBUS on architectures not supporting unaligned memory accesses ( 64 - bit
MIPS CPU ? ) : on such architecture , the structure must not be packed . */
architectures : 12 bytes instead of 16. */
typedef struct
# ifdef __GNUC__
__attribute__ ( ( packed ) )
@ -71,6 +88,7 @@ _declspec(align(4))
unsigned int lineno ;
} frame_t ;
typedef struct {
Py_uhash_t hash ;
int nframe ;
@ -83,6 +101,7 @@ typedef struct {
# define MAX_NFRAME \
( ( INT_MAX - ( int ) sizeof ( traceback_t ) ) / ( int ) sizeof ( frame_t ) + 1 )
static PyObject * unknown_filename = NULL ;
static traceback_t tracemalloc_empty_traceback ;
@ -95,6 +114,7 @@ typedef struct {
traceback_t * traceback ;
} trace_t ;
/* Size in bytes of currently traced memory.
Protected by TABLES_LOCK ( ) . */
static size_t tracemalloc_traced_memory = 0 ;
@ -121,6 +141,7 @@ static _Py_hashtable_t *tracemalloc_tracebacks = NULL;
Protected by TABLES_LOCK ( ) . */
static _Py_hashtable_t * tracemalloc_traces = NULL ;
# ifdef TRACE_DEBUG
static void
tracemalloc_error ( const char * format , . . . )
@ -135,6 +156,7 @@ tracemalloc_error(const char *format, ...)
}
# endif
# if defined(WITH_THREAD) && defined(TRACE_RAW_MALLOC)
# define REENTRANT_THREADLOCAL
@ -196,6 +218,7 @@ set_reentrant(int reentrant)
}
# endif
static Py_uhash_t
hashtable_hash_pyobject ( size_t key_size , const void * pkey )
{
@ -205,21 +228,53 @@ hashtable_hash_pyobject(size_t key_size, const void *pkey)
return PyObject_Hash ( obj ) ;
}
static int
hashtable_compare_unicode ( size_t key_size , const void * pkey ,
const _Py_hashtable_entry_t * entry )
{
PyObject * key , * entry_ key;
PyObject * key1 , * key2 ;
_Py_HASHTABLE_READ_KEY ( key_size , pkey , key ) ;
_Py_HASHTABLE_ENTRY_READ_KEY ( key_size , entry , entry_ key) ;
_Py_HASHTABLE_READ_KEY ( key_size , pkey , key1 ) ;
_Py_HASHTABLE_ENTRY_READ_KEY ( key_size , entry , key2 ) ;
if ( key ! = NULL & & entry_ key ! = NULL )
return ( PyUnicode_Compare ( key , entry_ key) = = 0 ) ;
if ( key1 ! = NULL & & key2 ! = NULL )
return ( PyUnicode_Compare ( key1 , key2 ) = = 0 ) ;
else
return key = = entry_key ;
return key1 = = key2 ;
}
static Py_uhash_t
hashtable_hash_pointer_t ( size_t key_size , const void * pkey )
{
pointer_t ptr ;
Py_uhash_t hash ;
_Py_HASHTABLE_READ_KEY ( key_size , pkey , ptr ) ;
hash = ( Py_uhash_t ) _Py_HashPointer ( ( void * ) ptr . ptr ) ;
hash ^ = ptr . domain ;
return hash ;
}
int
hashtable_compare_pointer_t ( size_t key_size , const void * pkey ,
const _Py_hashtable_entry_t * entry )
{
pointer_t ptr1 , ptr2 ;
_Py_HASHTABLE_READ_KEY ( key_size , pkey , ptr1 ) ;
_Py_HASHTABLE_ENTRY_READ_KEY ( key_size , entry , ptr2 ) ;
/* compare pointer before domain, because pointer is more likely to be
different */
return ( ptr1 . ptr = = ptr2 . ptr & & ptr1 . domain = = ptr2 . domain ) ;
}
static _Py_hashtable_t *
hashtable_new ( size_t key_size , size_t data_size ,
_Py_hashtable_hash_func hash_func ,
@ -231,6 +286,7 @@ hashtable_new(size_t key_size, size_t data_size,
& hashtable_alloc ) ;
}
static void *
raw_malloc ( size_t size )
{
@ -243,6 +299,7 @@ raw_free(void *ptr)
allocators . raw . free ( allocators . raw . ctx , ptr ) ;
}
static Py_uhash_t
hashtable_hash_traceback ( size_t key_size , const void * pkey )
{
@ -252,6 +309,7 @@ hashtable_hash_traceback(size_t key_size, const void *pkey)
return traceback - > hash ;
}
static int
hashtable_compare_traceback ( size_t key_size , const void * pkey ,
const _Py_hashtable_entry_t * he )
@ -281,6 +339,7 @@ hashtable_compare_traceback(size_t key_size, const void *pkey,
return 1 ;
}
static void
tracemalloc_get_frame ( PyFrameObject * pyframe , frame_t * frame )
{
@ -353,6 +412,7 @@ tracemalloc_get_frame(PyFrameObject *pyframe, frame_t *frame)
frame - > filename = filename ;
}
static Py_uhash_t
traceback_hash ( traceback_t * traceback )
{
@ -377,6 +437,7 @@ traceback_hash(traceback_t *traceback)
return x ;
}
static void
traceback_get_frames ( traceback_t * traceback )
{
@ -404,6 +465,7 @@ traceback_get_frames(traceback_t *traceback)
}
}
static traceback_t *
traceback_new ( void )
{
@ -455,41 +517,72 @@ traceback_new(void)
return traceback ;
}
static void
tracemalloc_remove_trace ( domain_t domain , Py_uintptr_t ptr )
{
trace_t trace ;
int removed ;
if ( tracemalloc_config . use_domain ) {
pointer_t key = { ptr , domain } ;
removed = _Py_HASHTABLE_POP ( tracemalloc_traces , key , trace ) ;
}
else {
removed = _Py_HASHTABLE_POP ( tracemalloc_traces , ptr , trace ) ;
}
if ( ! removed ) {
return ;
}
assert ( tracemalloc_traced_memory > = trace . size ) ;
tracemalloc_traced_memory - = trace . size ;
}
# define REMOVE_TRACE(ptr) \
tracemalloc_remove_trace ( DEFAULT_DOMAIN , ( Py_uintptr_t ) ( ptr ) )
static int
tracemalloc_add_trace ( void * ptr , size_t size )
tracemalloc_add_trace ( domain_t domain , Py_uintptr_t ptr , size_t size )
{
traceback_t * traceback ;
trace_t trace ;
int res ;
/* first, remove the previous trace (if any) */
tracemalloc_remove_trace ( domain , ptr ) ;
traceback = traceback_new ( ) ;
if ( traceback = = NULL )
if ( traceback = = NULL ) {
return - 1 ;
}
trace . size = size ;
trace . traceback = traceback ;
res = _Py_HASHTABLE_SET ( tracemalloc_traces , ptr , trace ) ;
if ( res = = 0 ) {
assert ( tracemalloc_traced_memory < = PY_SIZE_MAX - size ) ;
tracemalloc_traced_memory + = size ;
if ( tracemalloc_traced_memory > tracemalloc_peak_traced_memory )
tracemalloc_peak_traced_memory = tracemalloc_traced_memory ;
if ( tracemalloc_config . use_domain ) {
pointer_t key = { ptr , domain } ;
res = _Py_HASHTABLE_SET ( tracemalloc_traces , key , trace ) ;
}
else {
res = _Py_HASHTABLE_SET ( tracemalloc_traces , ptr , trace ) ;
}
if ( res ! = 0 ) {
return res ;
}
return res ;
assert ( tracemalloc_traced_memory < = PY_SIZE_MAX - size ) ;
tracemalloc_traced_memory + = size ;
if ( tracemalloc_traced_memory > tracemalloc_peak_traced_memory )
tracemalloc_peak_traced_memory = tracemalloc_traced_memory ;
return 0 ;
}
static void
tracemalloc_remove_trace ( void * ptr )
{
trace_t trace ;
# define ADD_TRACE(ptr, size) \
tracemalloc_add_trace ( DEFAULT_DOMAIN , ( Py_uintptr_t ) ( ptr ) , size )
if ( _Py_HASHTABLE_POP ( tracemalloc_traces , ptr , trace ) ) {
assert ( tracemalloc_traced_memory > = trace . size ) ;
tracemalloc_traced_memory - = trace . size ;
}
}
static void *
tracemalloc_alloc ( int use_calloc , void * ctx , size_t nelem , size_t elsize )
@ -507,7 +600,7 @@ tracemalloc_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize)
return NULL ;
TABLES_LOCK ( ) ;
if ( tracemalloc_add_trace ( ptr , nelem * elsize ) < 0 ) {
if ( ADD_TRACE ( ptr , nelem * elsize ) < 0 ) {
/* Failed to allocate a trace for the new memory block */
TABLES_UNLOCK ( ) ;
alloc - > free ( alloc - > ctx , ptr ) ;
@ -517,6 +610,7 @@ tracemalloc_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize)
return ptr ;
}
static void *
tracemalloc_realloc ( void * ctx , void * ptr , size_t new_size )
{
@ -531,9 +625,9 @@ tracemalloc_realloc(void *ctx, void *ptr, size_t new_size)
/* an existing memory block has been resized */
TABLES_LOCK ( ) ;
tracemalloc_remove_trace ( ptr ) ;
REMOVE_TRACE ( ptr ) ;
if ( tracemalloc_add_trace ( ptr2 , new_size ) < 0 ) {
if ( ADD_TRACE ( ptr2 , new_size ) < 0 ) {
/* Memory allocation failed. The error cannot be reported to
the caller , because realloc ( ) may already have shrinked the
memory block and so removed bytes .
@ -551,7 +645,7 @@ tracemalloc_realloc(void *ctx, void *ptr, size_t new_size)
/* new allocation */
TABLES_LOCK ( ) ;
if ( tracemalloc_add_trace ( ptr2 , new_size ) < 0 ) {
if ( ADD_TRACE ( ptr2 , new_size ) < 0 ) {
/* Failed to allocate a trace for the new memory block */
TABLES_UNLOCK ( ) ;
alloc - > free ( alloc - > ctx , ptr2 ) ;
@ -562,6 +656,7 @@ tracemalloc_realloc(void *ctx, void *ptr, size_t new_size)
return ptr2 ;
}
static void
tracemalloc_free ( void * ctx , void * ptr )
{
@ -576,10 +671,11 @@ tracemalloc_free(void *ctx, void *ptr)
alloc - > free ( alloc - > ctx , ptr ) ;
TABLES_LOCK ( ) ;
tracemalloc_remove_trace ( ptr ) ;
REMOVE_TRACE ( ptr ) ;
TABLES_UNLOCK ( ) ;
}
static void *
tracemalloc_alloc_gil ( int use_calloc , void * ctx , size_t nelem , size_t elsize )
{
@ -604,18 +700,21 @@ tracemalloc_alloc_gil(int use_calloc, void *ctx, size_t nelem, size_t elsize)
return ptr ;
}
static void *
tracemalloc_malloc_gil ( void * ctx , size_t size )
{
return tracemalloc_alloc_gil ( 0 , ctx , 1 , size ) ;
}
static void *
tracemalloc_calloc_gil ( void * ctx , size_t nelem , size_t elsize )
{
return tracemalloc_alloc_gil ( 1 , ctx , nelem , elsize ) ;
}
static void *
tracemalloc_realloc_gil ( void * ctx , void * ptr , size_t new_size )
{
@ -631,7 +730,7 @@ tracemalloc_realloc_gil(void *ctx, void *ptr, size_t new_size)
ptr2 = alloc - > realloc ( alloc - > ctx , ptr , new_size ) ;
if ( ptr2 ! = NULL & & ptr ! = NULL ) {
TABLES_LOCK ( ) ;
tracemalloc_remove_trace ( ptr ) ;
REMOVE_TRACE ( ptr ) ;
TABLES_UNLOCK ( ) ;
}
return ptr2 ;
@ -648,6 +747,7 @@ tracemalloc_realloc_gil(void *ctx, void *ptr, size_t new_size)
return ptr2 ;
}
# ifdef TRACE_RAW_MALLOC
static void *
tracemalloc_raw_alloc ( int use_calloc , void * ctx , size_t nelem , size_t elsize )
@ -682,18 +782,21 @@ tracemalloc_raw_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize)
return ptr ;
}
static void *
tracemalloc_raw_malloc ( void * ctx , size_t size )
{
return tracemalloc_raw_alloc ( 0 , ctx , 1 , size ) ;
}
static void *
tracemalloc_raw_calloc ( void * ctx , size_t nelem , size_t elsize )
{
return tracemalloc_raw_alloc ( 1 , ctx , nelem , elsize ) ;
}
static void *
tracemalloc_raw_realloc ( void * ctx , void * ptr , size_t new_size )
{
@ -710,7 +813,7 @@ tracemalloc_raw_realloc(void *ctx, void *ptr, size_t new_size)
if ( ptr2 ! = NULL & & ptr ! = NULL ) {
TABLES_LOCK ( ) ;
tracemalloc_remove_trace ( ptr ) ;
REMOVE_TRACE ( ptr ) ;
TABLES_UNLOCK ( ) ;
}
return ptr2 ;
@ -734,6 +837,7 @@ tracemalloc_raw_realloc(void *ctx, void *ptr, size_t new_size)
}
# endif /* TRACE_RAW_MALLOC */
static int
tracemalloc_clear_filename ( _Py_hashtable_t * ht , _Py_hashtable_entry_t * entry ,
void * user_data )
@ -745,6 +849,7 @@ tracemalloc_clear_filename(_Py_hashtable_t *ht, _Py_hashtable_entry_t *entry,
return 0 ;
}
static int
traceback_free_traceback ( _Py_hashtable_t * ht , _Py_hashtable_entry_t * entry ,
void * user_data )
@ -756,6 +861,7 @@ traceback_free_traceback(_Py_hashtable_t *ht, _Py_hashtable_entry_t *entry,
return 0 ;
}
/* reentrant flag must be set to call this function and GIL must be held */
static void
tracemalloc_clear_traces ( void )
@ -782,6 +888,7 @@ tracemalloc_clear_traces(void)
_Py_hashtable_clear ( tracemalloc_filenames ) ;
}
static int
tracemalloc_init ( void )
{
@ -826,9 +933,18 @@ tracemalloc_init(void)
hashtable_hash_traceback ,
hashtable_compare_traceback ) ;
tracemalloc_traces = hashtable_new ( sizeof ( void * ) , sizeof ( trace_t ) ,
_Py_hashtable_hash_ptr ,
_Py_hashtable_compare_direct ) ;
if ( tracemalloc_config . use_domain ) {
tracemalloc_traces = hashtable_new ( sizeof ( pointer_t ) ,
sizeof ( trace_t ) ,
hashtable_hash_pointer_t ,
hashtable_compare_pointer_t ) ;
}
else {
tracemalloc_traces = hashtable_new ( sizeof ( Py_uintptr_t ) ,
sizeof ( trace_t ) ,
_Py_hashtable_hash_ptr ,
_Py_hashtable_compare_direct ) ;
}
if ( tracemalloc_filenames = = NULL | | tracemalloc_tracebacks = = NULL
| | tracemalloc_traces = = NULL ) {
@ -856,6 +972,7 @@ tracemalloc_init(void)
return 0 ;
}
static void
tracemalloc_deinit ( void )
{
@ -884,6 +1001,7 @@ tracemalloc_deinit(void)
Py_XDECREF ( unknown_filename ) ;
}
static int
tracemalloc_start ( int max_nframe )
{
@ -941,6 +1059,7 @@ tracemalloc_start(int max_nframe)
return 0 ;
}
static void
tracemalloc_stop ( void )
{
@ -974,6 +1093,7 @@ PyDoc_STRVAR(tracemalloc_is_tracing_doc,
" True if the tracemalloc module is tracing Python memory allocations, \n "
" False otherwise. " ) ;
static PyObject *
py_tracemalloc_is_tracing ( PyObject * self )
{
@ -985,6 +1105,7 @@ PyDoc_STRVAR(tracemalloc_clear_traces_doc,
" \n "
" Clear traces of memory blocks allocated by Python. " ) ;
static PyObject *
py_tracemalloc_clear_traces ( PyObject * self )
{
@ -998,6 +1119,7 @@ py_tracemalloc_clear_traces(PyObject *self)
Py_RETURN_NONE ;
}
static PyObject *
frame_to_pyobject ( frame_t * frame )
{
@ -1020,6 +1142,7 @@ frame_to_pyobject(frame_t *frame)
return frame_obj ;
}
static PyObject *
traceback_to_pyobject ( traceback_t * traceback , _Py_hashtable_t * intern_table )
{
@ -1058,33 +1181,43 @@ traceback_to_pyobject(traceback_t *traceback, _Py_hashtable_t *intern_table)
return frames ;
}
static PyObject *
trace_to_pyobject ( trace_t * trace , _Py_hashtable_t * intern_tracebacks )
trace_to_pyobject ( domain_t domain , trace_t * trace ,
_Py_hashtable_t * intern_tracebacks )
{
PyObject * trace_obj = NULL ;
PyObject * size , * traceback ;
PyObject * obj ;
trace_obj = PyTuple_New ( 2 ) ;
trace_obj = PyTuple_New ( 3 ) ;
if ( trace_obj = = NULL )
return NULL ;
size = PyLong_FromSize_t ( trace - > size ) ;
if ( size = = NULL ) {
obj = PyLong_FromSize_t ( domain ) ;
if ( obj = = NULL ) {
Py_DECREF ( trace_obj ) ;
return NULL ;
}
PyTuple_SET_ITEM ( trace_obj , 0 , size ) ;
PyTuple_SET_ITEM ( trace_obj , 0 , obj ) ;
traceback = traceback_to_pyobject ( trace - > traceback , intern_tracebacks ) ;
if ( traceback = = NULL ) {
obj = PyLong_FromSize_t ( trace - > size ) ;
if ( obj = = NULL ) {
Py_DECREF ( trace_obj ) ;
return NULL ;
}
PyTuple_SET_ITEM ( trace_obj , 1 , obj ) ;
obj = traceback_to_pyobject ( trace - > traceback , intern_tracebacks ) ;
if ( obj = = NULL ) {
Py_DECREF ( trace_obj ) ;
return NULL ;
}
PyTuple_SET_ITEM ( trace_obj , 1 , traceback ) ;
PyTuple_SET_ITEM ( trace_obj , 2 , obj ) ;
return trace_obj ;
}
typedef struct {
_Py_hashtable_t * traces ;
_Py_hashtable_t * tracebacks ;
@ -1096,13 +1229,22 @@ tracemalloc_get_traces_fill(_Py_hashtable_t *traces, _Py_hashtable_entry_t *entr
void * user_data )
{
get_traces_t * get_traces = user_data ;
domain_t domain ;
trace_t * trace ;
PyObject * tracemalloc_obj ;
int res ;
if ( tracemalloc_config . use_domain ) {
pointer_t key ;
_Py_HASHTABLE_ENTRY_READ_KEY ( traces - > key_size , entry , key ) ;
domain = key . domain ;
}
else {
domain = DEFAULT_DOMAIN ;
}
trace = ( trace_t * ) _Py_HASHTABLE_ENTRY_DATA ( traces , entry ) ;
tracemalloc_obj = trace_to_pyobject ( trace , get_traces - > tracebacks ) ;
tracemalloc_obj = trace_to_pyobject ( domain , trace , get_traces - > tracebacks ) ;
if ( tracemalloc_obj = = NULL )
return 1 ;
@ -1114,6 +1256,7 @@ tracemalloc_get_traces_fill(_Py_hashtable_t *traces, _Py_hashtable_entry_t *entr
return 0 ;
}
static int
tracemalloc_pyobject_decref_cb ( _Py_hashtable_t * tracebacks ,
_Py_hashtable_entry_t * entry ,
@ -1125,6 +1268,7 @@ tracemalloc_pyobject_decref_cb(_Py_hashtable_t *tracebacks,
return 0 ;
}
PyDoc_STRVAR ( tracemalloc_get_traces_doc ,
" _get_traces() -> list \n "
" \n "
@ -1194,8 +1338,9 @@ finally:
return get_traces . list ;
}
static traceback_t *
tracemalloc_get_traceback ( const void * ptr )
tracemalloc_get_traceback ( domain_t domain , const void * ptr )
{
trace_t trace ;
int found ;
@ -1204,7 +1349,13 @@ tracemalloc_get_traceback(const void *ptr)
return NULL ;
TABLES_LOCK ( ) ;
found = _Py_HASHTABLE_GET ( tracemalloc_traces , ptr , trace ) ;
if ( tracemalloc_config . use_domain ) {
pointer_t key = { ( Py_uintptr_t ) ptr , domain } ;
found = _Py_HASHTABLE_GET ( tracemalloc_traces , key , trace ) ;
}
else {
found = _Py_HASHTABLE_GET ( tracemalloc_traces , ptr , trace ) ;
}
TABLES_UNLOCK ( ) ;
if ( ! found )
@ -1213,6 +1364,7 @@ tracemalloc_get_traceback(const void *ptr)
return trace . traceback ;
}
PyDoc_STRVAR ( tracemalloc_get_object_traceback_doc ,
" _get_object_traceback(obj) \n "
" \n "
@ -1235,13 +1387,14 @@ py_tracemalloc_get_object_traceback(PyObject *self, PyObject *obj)
else
ptr = ( void * ) obj ;
traceback = tracemalloc_get_traceback ( ptr ) ;
traceback = tracemalloc_get_traceback ( DEFAULT_DOMAIN , ptr ) ;
if ( traceback = = NULL )
Py_RETURN_NONE ;
return traceback_to_pyobject ( traceback , NULL ) ;
}
# define PUTS(fd, str) _Py_write_noraise(fd, str, (int)strlen(str))
static void
@ -1262,7 +1415,7 @@ _PyMem_DumpTraceback(int fd, const void *ptr)
traceback_t * traceback ;
int i ;
traceback = tracemalloc_get_traceback ( ptr ) ;
traceback = tracemalloc_get_traceback ( DEFAULT_DOMAIN , ptr ) ;
if ( traceback = = NULL )
return ;
@ -1275,6 +1428,7 @@ _PyMem_DumpTraceback(int fd, const void *ptr)
# undef PUTS
PyDoc_STRVAR ( tracemalloc_start_doc ,
" start(nframe: int=1) \n "
" \n "
@ -1310,6 +1464,7 @@ PyDoc_STRVAR(tracemalloc_stop_doc,
" Stop tracing Python memory allocations and clear traces \n "
" of memory blocks allocated by Python. " ) ;
static PyObject *
py_tracemalloc_stop ( PyObject * self )
{
@ -1317,6 +1472,7 @@ py_tracemalloc_stop(PyObject *self)
Py_RETURN_NONE ;
}
PyDoc_STRVAR ( tracemalloc_get_traceback_limit_doc ,
" get_traceback_limit() -> int \n "
" \n "
@ -1332,6 +1488,7 @@ py_tracemalloc_get_traceback_limit(PyObject *self)
return PyLong_FromLong ( tracemalloc_config . max_nframe ) ;
}
PyDoc_STRVAR ( tracemalloc_get_tracemalloc_memory_doc ,
" get_tracemalloc_memory() -> int \n "
" \n "
@ -1355,6 +1512,7 @@ tracemalloc_get_tracemalloc_memory(PyObject *self)
return Py_BuildValue ( " N " , size_obj ) ;
}
PyDoc_STRVAR ( tracemalloc_get_traced_memory_doc ,
" get_traced_memory() -> (int, int) \n "
" \n "
@ -1380,6 +1538,7 @@ tracemalloc_get_traced_memory(PyObject *self)
return Py_BuildValue ( " NN " , size_obj , peak_size_obj ) ;
}
static PyMethodDef module_methods [ ] = {
{ " is_tracing " , ( PyCFunction ) py_tracemalloc_is_tracing ,
METH_NOARGS , tracemalloc_is_tracing_doc } ,
@ -1430,6 +1589,7 @@ PyInit__tracemalloc(void)
return m ;
}
static int
parse_sys_xoptions ( PyObject * value )
{
@ -1458,6 +1618,7 @@ parse_sys_xoptions(PyObject *value)
return Py_SAFE_DOWNCAST ( nframe , long , int ) ;
}
int
_PyTraceMalloc_Init ( void )
{
@ -1516,6 +1677,7 @@ _PyTraceMalloc_Init(void)
return tracemalloc_start ( nframe ) ;
}
void
_PyTraceMalloc_Fini ( void )
{
@ -1524,4 +1686,3 @@ _PyTraceMalloc_Fini(void)
# endif
tracemalloc_deinit ( ) ;
}