[Python-checkins] bpo-46072: Add simple stats for Python calls. (GH-30989)

markshannon webhook-mailer at python.org
Fri Jan 28 10:20:57 EST 2022


https://github.com/python/cpython/commit/90ab138bbdc63763ad825ed6d4821367c09c4015
commit: 90ab138bbdc63763ad825ed6d4821367c09c4015
branch: main
author: Mark Shannon <mark at hotpy.org>
committer: markshannon <mark at hotpy.org>
date: 2022-01-28T15:20:33Z
summary:

bpo-46072: Add simple stats for Python calls. (GH-30989)

files:
M Include/internal/pycore_code.h
M Python/ceval.c
M Python/specialize.c
M Tools/scripts/summarize_stats.py

diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h
index 71dfe3e9da0d2..68b536f75ca5e 100644
--- a/Include/internal/pycore_code.h
+++ b/Include/internal/pycore_code.h
@@ -300,8 +300,14 @@ typedef struct _opcode_stats {
     uint64_t pair_count[256];
 } OpcodeStats;
 
+typedef struct _call_stats {
+    uint64_t inlined_py_calls;
+    uint64_t pyeval_calls;
+} CallStats;
+
 typedef struct _stats {
     OpcodeStats opcode_stats[256];
+    CallStats call_stats;
 } PyStats;
 
 extern PyStats _py_stats;
@@ -309,6 +315,7 @@ extern PyStats _py_stats;
 #define STAT_INC(opname, name) _py_stats.opcode_stats[opname].specialization.name++
 #define STAT_DEC(opname, name) _py_stats.opcode_stats[opname].specialization.name--
 #define OPCODE_EXE_INC(opname) _py_stats.opcode_stats[opname].execution_count++
+#define CALL_STAT_INC(name) _py_stats.call_stats.name++
 
 void _Py_PrintSpecializationStats(int to_file);
 
@@ -318,6 +325,7 @@ PyAPI_FUNC(PyObject*) _Py_GetSpecializationStats(void);
 #define STAT_INC(opname, name) ((void)0)
 #define STAT_DEC(opname, name) ((void)0)
 #define OPCODE_EXE_INC(opname) ((void)0)
+#define CALL_STAT_INC(name) ((void)0)
 #endif
 
 
diff --git a/Python/ceval.c b/Python/ceval.c
index cd05780b16ecc..fa14a1c04f1e0 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -1651,6 +1651,7 @@ PyObject* _Py_HOT_FUNCTION
 _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int throwflag)
 {
     _Py_EnsureTstateNotNULL(tstate);
+    CALL_STAT_INC(pyeval_calls);
 
 #if USE_COMPUTED_GOTOS
 /* Import the static jump table */
@@ -2252,6 +2253,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
             _PyFrame_SetStackPointer(frame, stack_pointer);
             new_frame->previous = frame;
             frame = cframe.current_frame = new_frame;
+            CALL_STAT_INC(inlined_py_calls);
             goto start_frame;
         }
 
@@ -4589,6 +4591,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
                 _PyFrame_SetStackPointer(frame, stack_pointer);
                 new_frame->previous = frame;
                 cframe.current_frame = frame = new_frame;
+                CALL_STAT_INC(inlined_py_calls);
                 goto start_frame;
             }
             /* Callable is not a normal Python function */
@@ -4705,6 +4708,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
             _PyFrame_SetStackPointer(frame, stack_pointer);
             new_frame->previous = frame;
             frame = cframe.current_frame = new_frame;
+            CALL_STAT_INC(inlined_py_calls);
             goto start_frame;
         }
 
diff --git a/Python/specialize.c b/Python/specialize.c
index a69b73cff3e40..aec94d9e60be4 100644
--- a/Python/specialize.c
+++ b/Python/specialize.c
@@ -163,9 +163,18 @@ print_spec_stats(FILE *out, OpcodeStats *stats)
 }
 #undef PRINT_STAT
 
+
+static void
+print_call_stats(FILE *out, CallStats *stats)
+{
+    fprintf(out, "Calls to PyEval_EvalDefault: %" PRIu64 "\n", stats->pyeval_calls);
+    fprintf(out, "Calls to Python functions inlined: %" PRIu64 "\n", stats->inlined_py_calls);
+}
+
 static void
 print_stats(FILE *out, PyStats *stats) {
     print_spec_stats(out, stats->opcode_stats);
+    print_call_stats(out, &stats->call_stats);
 }
 
 void
diff --git a/Tools/scripts/summarize_stats.py b/Tools/scripts/summarize_stats.py
index 3a77125035a32..34cbad5fa7ea2 100644
--- a/Tools/scripts/summarize_stats.py
+++ b/Tools/scripts/summarize_stats.py
@@ -98,6 +98,14 @@ def main():
     for i, opcode_stat in enumerate(opcode_stats):
         name = opname[i]
         print_specialization_stats(name, opcode_stat)
+    print("Call stats:")
+    total = 0
+    for key, value in stats.items():
+        if "Calls to" in key:
+            total += value
+    for key, value in stats.items():
+        if "Calls to" in key:
+            print(f"{key}: {value} {100*value/total:0.1f}%")
 
 if __name__ == "__main__":
     main()



More information about the Python-checkins mailing list