From c686a7db09e87d5ab8e38ab5ff1d602cf3eaa2dc Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Tue, 18 Jan 2022 13:27:36 +0000 Subject: [PATCH 1/2] Add simple stats for Python calls. --- Include/internal/pycore_code.h | 8 ++++++++ Python/ceval.c | 4 ++++ Python/specialize.c | 9 +++++++++ Tools/scripts/summarize_stats.py | 8 ++++++++ 4 files changed, 29 insertions(+) diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h index 71dfe3e9da0d24..68b536f75ca5e0 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 cd05780b16eccf..e273e42105c1e0 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 a69b73cff3e403..aec94d9e60be41 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 3a77125035a321..34cbad5fa7ea25 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() From d44a34c9a6667c3d2b8101a99e453d1a57a2ee56 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Fri, 28 Jan 2022 14:27:28 +0000 Subject: [PATCH 2/2] Fix indentation --- Python/ceval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Python/ceval.c b/Python/ceval.c index e273e42105c1e0..fa14a1c04f1e0c 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4591,7 +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); + CALL_STAT_INC(inlined_py_calls); goto start_frame; } /* Callable is not a normal Python function */