diff options
author | Mark Shannon <mark@hotpy.org> | 2022-01-28 15:20:33 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-28 15:20:33 (GMT) |
commit | 90ab138bbdc63763ad825ed6d4821367c09c4015 (patch) | |
tree | 3adaef410013002de2e488d9c37fb6abc3462082 | |
parent | 9a241271139a317597aca71d5971346b2cfe7dbd (diff) | |
download | cpython-90ab138bbdc63763ad825ed6d4821367c09c4015.zip cpython-90ab138bbdc63763ad825ed6d4821367c09c4015.tar.gz cpython-90ab138bbdc63763ad825ed6d4821367c09c4015.tar.bz2 |
bpo-46072: Add simple stats for Python calls. (GH-30989)
-rw-r--r-- | Include/internal/pycore_code.h | 8 | ||||
-rw-r--r-- | Python/ceval.c | 4 | ||||
-rw-r--r-- | Python/specialize.c | 9 | ||||
-rw-r--r-- | Tools/scripts/summarize_stats.py | 8 |
4 files changed, 29 insertions, 0 deletions
diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h index 71dfe3e..68b536f 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 cd05780..fa14a1c 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 @@ handle_eval_breaker: _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 @@ handle_eval_breaker: _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 @@ handle_eval_breaker: _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 a69b73c..aec94d9 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 3a77125..34cbad5 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() |