Skip to content

Commit

Permalink
bpo-46072: Add simple stats for Python calls. (GH-30989)
Browse files Browse the repository at this point in the history
  • Loading branch information
markshannon authored Jan 28, 2022
1 parent 9a24127 commit 90ab138
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 0 deletions.
8 changes: 8 additions & 0 deletions Include/internal/pycore_code.h
Original file line number Diff line number Diff line change
Expand Up @@ -300,15 +300,22 @@ 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;

#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);

Expand All @@ -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


Expand Down
4 changes: 4 additions & 0 deletions Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
}

Expand Down
9 changes: 9 additions & 0 deletions Python/specialize.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 8 additions & 0 deletions Tools/scripts/summarize_stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()

0 comments on commit 90ab138

Please sign in to comment.