diff --git a/Include/pystats.h b/Include/pystats.h index bc05dd864c6..4375614b05e 100644 --- a/Include/pystats.h +++ b/Include/pystats.h @@ -36,6 +36,8 @@ typedef struct _call_stats { typedef struct _object_stats { uint64_t increfs; uint64_t decrefs; + uint64_t interpreter_increfs; + uint64_t interpreter_decrefs; uint64_t allocations; uint64_t allocations512; uint64_t allocations4k; @@ -60,10 +62,18 @@ PyAPI_DATA(PyStats) _py_stats; extern void _Py_PrintSpecializationStats(int to_file); +#ifdef _PY_INTERPRETER + +#define _Py_INCREF_STAT_INC() _py_stats.object_stats.interpreter_increfs++ +#define _Py_DECREF_STAT_INC() _py_stats.object_stats.interpreter_decrefs++ + +#else #define _Py_INCREF_STAT_INC() _py_stats.object_stats.increfs++ #define _Py_DECREF_STAT_INC() _py_stats.object_stats.decrefs++ +#endif + #else #define _Py_INCREF_STAT_INC() ((void)0) diff --git a/Objects/genobject.c b/Objects/genobject.c index b9a0c30c411..a88522abf41 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -1,5 +1,7 @@ /* Generator object implementation */ +#define _PY_INTERPRETER + #include "Python.h" #include "pycore_call.h" // _PyObject_CallNoArgs() #include "pycore_ceval.h" // _PyEval_EvalFrame() diff --git a/Python/ceval.c b/Python/ceval.c index c81d0efff9b..e4c47498c0c 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -5,6 +5,8 @@ XXX document it! */ +#define _PY_INTERPRETER + #include "Python.h" #include "pycore_abstract.h" // _PyIndex_Check() #include "pycore_call.h" // _PyObject_FastCallDictTstate() diff --git a/Python/frame.c b/Python/frame.c index c2da123a2bb..3573f54ad63 100644 --- a/Python/frame.c +++ b/Python/frame.c @@ -1,4 +1,6 @@ +#define _PY_INTERPRETER + #include "Python.h" #include "frameobject.h" #include "pycore_code.h" // stats diff --git a/Python/specialize.c b/Python/specialize.c index 6a91389f856..5469285e16c 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -191,6 +191,8 @@ print_object_stats(FILE *out, ObjectStats *stats) fprintf(out, "Object allocations over 4 kbytes: %" PRIu64 "\n", stats->allocations_big); fprintf(out, "Object frees: %" PRIu64 "\n", stats->frees); fprintf(out, "Object new values: %" PRIu64 "\n", stats->new_values); + fprintf(out, "Object interpreter increfs: %" PRIu64 "\n", stats->interpreter_increfs); + fprintf(out, "Object interpreter decrefs: %" PRIu64 "\n", stats->interpreter_decrefs); fprintf(out, "Object increfs: %" PRIu64 "\n", stats->increfs); fprintf(out, "Object decrefs: %" PRIu64 "\n", stats->decrefs); fprintf(out, "Object materialize dict (on request): %" PRIu64 "\n", stats->dict_materialized_on_request); diff --git a/Tools/scripts/summarize_stats.py b/Tools/scripts/summarize_stats.py index f66fc7b6845..3d7479f261b 100644 --- a/Tools/scripts/summarize_stats.py +++ b/Tools/scripts/summarize_stats.py @@ -272,6 +272,8 @@ def emit_object_stats(stats): with Section("Object stats", summary="allocations, frees and dict materializatons"): total_materializations = stats.get("Object new values") total_allocations = stats.get("Object allocations") + total_increfs = stats.get("Object interpreter increfs") + stats.get("Object increfs") + total_decrefs = stats.get("Object interpreter decrefs") + stats.get("Object decrefs") rows = [] for key, value in stats.items(): if key.startswith("Object"): @@ -279,6 +281,10 @@ def emit_object_stats(stats): ratio = f"{100*value/total_materializations:0.1f}%" elif "allocations" in key: ratio = f"{100*value/total_allocations:0.1f}%" + elif "increfs" in key: + ratio = f"{100*value/total_increfs:0.1f}%" + elif "decrefs" in key: + ratio = f"{100*value/total_decrefs:0.1f}%" else: ratio = "" label = key[6:].strip()