mirror of https://github.com/python/cpython
bpo-46072: Add simple stats for Python calls. (GH-30989)
This commit is contained in:
parent
9a24127113
commit
90ab138bbd
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue