Kaydet (Commit) 45294a95 authored tarafından Martin v. Löwis's avatar Martin v. Löwis

Remove types from type_list if they have no objects

and unlist_types_without_objects is set.
Give dump_counts a FILE* argument.
üst 041669fa
...@@ -339,6 +339,7 @@ typedef struct _typeobject { ...@@ -339,6 +339,7 @@ typedef struct _typeobject {
Py_ssize_t tp_allocs; Py_ssize_t tp_allocs;
Py_ssize_t tp_frees; Py_ssize_t tp_frees;
Py_ssize_t tp_maxalloc; Py_ssize_t tp_maxalloc;
struct _typeobject *tp_prev;
struct _typeobject *tp_next; struct _typeobject *tp_next;
#endif #endif
} PyTypeObject; } PyTypeObject;
...@@ -598,8 +599,9 @@ PyAPI_FUNC(Py_ssize_t) _Py_GetRefTotal(void); ...@@ -598,8 +599,9 @@ PyAPI_FUNC(Py_ssize_t) _Py_GetRefTotal(void);
#ifdef COUNT_ALLOCS #ifdef COUNT_ALLOCS
PyAPI_FUNC(void) inc_count(PyTypeObject *); PyAPI_FUNC(void) inc_count(PyTypeObject *);
PyAPI_FUNC(void) dec_count(PyTypeObject *);
#define _Py_INC_TPALLOCS(OP) inc_count((OP)->ob_type) #define _Py_INC_TPALLOCS(OP) inc_count((OP)->ob_type)
#define _Py_INC_TPFREES(OP) (OP)->ob_type->tp_frees++ #define _Py_INC_TPFREES(OP) dec_count((OP)->ob_type)
#define _Py_DEC_TPFREES(OP) (OP)->ob_type->tp_frees-- #define _Py_DEC_TPFREES(OP) (OP)->ob_type->tp_frees--
#define _Py_COUNT_ALLOCS_COMMA , #define _Py_COUNT_ALLOCS_COMMA ,
#else #else
......
...@@ -12,6 +12,8 @@ What's New in Python 2.5 alpha 2? ...@@ -12,6 +12,8 @@ What's New in Python 2.5 alpha 2?
Core and builtins Core and builtins
----------------- -----------------
- Under COUNT_ALLOCS, types are not necessarily immortal anymore.
- All uses of PyStructSequence_InitType have been changed to initialize - All uses of PyStructSequence_InitType have been changed to initialize
the type objects only once, even if the interpreter is initialized the type objects only once, even if the interpreter is initialized
multiple times. multiple times.
......
...@@ -74,23 +74,30 @@ _Py_AddToAllObjects(PyObject *op, int force) ...@@ -74,23 +74,30 @@ _Py_AddToAllObjects(PyObject *op, int force)
#ifdef COUNT_ALLOCS #ifdef COUNT_ALLOCS
static PyTypeObject *type_list; static PyTypeObject *type_list;
/* All types are added to type_list, atleast when
they get one object created. That makes them
immortal, which unfortunately contributes to
garbage itself. If unlist_types_without_objects
is set, they will be removed from the type_list
once the last object is deallocated. */
int unlist_types_without_objects;
extern int tuple_zero_allocs, fast_tuple_allocs; extern int tuple_zero_allocs, fast_tuple_allocs;
extern int quick_int_allocs, quick_neg_int_allocs; extern int quick_int_allocs, quick_neg_int_allocs;
extern int null_strings, one_strings; extern int null_strings, one_strings;
void void
dump_counts(void) dump_counts(FILE* f)
{ {
PyTypeObject *tp; PyTypeObject *tp;
for (tp = type_list; tp; tp = tp->tp_next) for (tp = type_list; tp; tp = tp->tp_next)
fprintf(stderr, "%s alloc'd: %d, freed: %d, max in use: %d\n", fprintf(f, "%s alloc'd: %d, freed: %d, max in use: %d\n",
tp->tp_name, tp->tp_allocs, tp->tp_frees, tp->tp_name, tp->tp_allocs, tp->tp_frees,
tp->tp_maxalloc); tp->tp_maxalloc);
fprintf(stderr, "fast tuple allocs: %d, empty: %d\n", fprintf(f, "fast tuple allocs: %d, empty: %d\n",
fast_tuple_allocs, tuple_zero_allocs); fast_tuple_allocs, tuple_zero_allocs);
fprintf(stderr, "fast int allocs: pos: %d, neg: %d\n", fprintf(f, "fast int allocs: pos: %d, neg: %d\n",
quick_int_allocs, quick_neg_int_allocs); quick_int_allocs, quick_neg_int_allocs);
fprintf(stderr, "null strings: %d, 1-strings: %d\n", fprintf(f, "null strings: %d, 1-strings: %d\n",
null_strings, one_strings); null_strings, one_strings);
} }
...@@ -124,10 +131,12 @@ get_counts(void) ...@@ -124,10 +131,12 @@ get_counts(void)
void void
inc_count(PyTypeObject *tp) inc_count(PyTypeObject *tp)
{ {
if (tp->tp_allocs == 0) { if (tp->tp_next == NULL && tp->tp_prev == NULL) {
/* first time; insert in linked list */ /* first time; insert in linked list */
if (tp->tp_next != NULL) /* sanity check */ if (tp->tp_next != NULL) /* sanity check */
Py_FatalError("XXX inc_count sanity check"); Py_FatalError("XXX inc_count sanity check");
if (type_list)
type_list->tp_prev = tp;
tp->tp_next = type_list; tp->tp_next = type_list;
/* Note that as of Python 2.2, heap-allocated type objects /* Note that as of Python 2.2, heap-allocated type objects
* can go away, but this code requires that they stay alive * can go away, but this code requires that they stay alive
...@@ -150,6 +159,24 @@ inc_count(PyTypeObject *tp) ...@@ -150,6 +159,24 @@ inc_count(PyTypeObject *tp)
if (tp->tp_allocs - tp->tp_frees > tp->tp_maxalloc) if (tp->tp_allocs - tp->tp_frees > tp->tp_maxalloc)
tp->tp_maxalloc = tp->tp_allocs - tp->tp_frees; tp->tp_maxalloc = tp->tp_allocs - tp->tp_frees;
} }
void dec_count(PyTypeObject *tp)
{
tp->tp_frees++;
if (unlist_types_without_objects &&
tp->tp_allocs == tp->tp_frees) {
/* unlink the type from type_list */
if (tp->tp_prev)
tp->tp_prev->tp_next = tp->tp_next;
else
type_list = tp->tp_next;
if (tp->tp_next)
tp->tp_next->tp_prev = tp->tp_prev;
tp->tp_next = tp->tp_prev = NULL;
Py_DECREF(tp);
}
}
#endif #endif
#ifdef Py_REF_DEBUG #ifdef Py_REF_DEBUG
......
...@@ -311,7 +311,7 @@ Py_Initialize(void) ...@@ -311,7 +311,7 @@ Py_Initialize(void)
#ifdef COUNT_ALLOCS #ifdef COUNT_ALLOCS
extern void dump_counts(void); extern void dump_counts(FILE*);
#endif #endif
/* Undo the effect of Py_Initialize(). /* Undo the effect of Py_Initialize().
...@@ -373,6 +373,13 @@ Py_Finalize(void) ...@@ -373,6 +373,13 @@ Py_Finalize(void)
* XXX I haven't seen a real-life report of either of these. * XXX I haven't seen a real-life report of either of these.
*/ */
PyGC_Collect(); PyGC_Collect();
#ifdef COUNT_ALLOCS
/* With COUNT_ALLOCS, it helps to run GC multiple times:
each collection might release some types from the type
list, so they become garbage. */
while (PyGC_Collect() > 0)
/* nothing */;
#endif
/* Destroy all modules */ /* Destroy all modules */
PyImport_Cleanup(); PyImport_Cleanup();
...@@ -401,7 +408,7 @@ Py_Finalize(void) ...@@ -401,7 +408,7 @@ Py_Finalize(void)
/* Debugging stuff */ /* Debugging stuff */
#ifdef COUNT_ALLOCS #ifdef COUNT_ALLOCS
dump_counts(); dump_counts(stdout);
#endif #endif
PRINT_TOTAL_REFS(); PRINT_TOTAL_REFS();
......
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