Skip to content

Commit 187930f

Browse files
authored
bpo-46072: Add some frame stats. (GH-31060)
1 parent a05866c commit 187930f

File tree

7 files changed

+16
-1
lines changed

7 files changed

+16
-1
lines changed

Include/internal/pycore_code.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,8 @@ typedef struct _opcode_stats {
303303
typedef struct _call_stats {
304304
uint64_t inlined_py_calls;
305305
uint64_t pyeval_calls;
306+
uint64_t frames_pushed;
307+
uint64_t frame_objects_created;
306308
} CallStats;
307309

308310
typedef struct _object_stats {

Objects/frameobject.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,7 @@ init_frame(InterpreterFrame *frame, PyFunctionObject *func, PyObject *locals)
794794
PyFrameObject*
795795
_PyFrame_New_NoTrack(PyCodeObject *code)
796796
{
797+
CALL_STAT_INC(frame_objects_created);
797798
int slots = code->co_nlocalsplus + code->co_stacksize;
798799
PyFrameObject *f = PyObject_GC_NewVar(PyFrameObject, &PyFrame_Type, slots);
799800
if (f == NULL) {

Python/ceval.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2242,6 +2242,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
22422242
if (new_frame == NULL) {
22432243
goto error;
22442244
}
2245+
CALL_STAT_INC(frames_pushed);
22452246
_PyFrame_InitializeSpecials(new_frame, getitem,
22462247
NULL, code->co_nlocalsplus);
22472248
STACK_SHRINK(2);
@@ -4660,6 +4661,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
46604661
if (new_frame == NULL) {
46614662
goto error;
46624663
}
4664+
CALL_STAT_INC(inlined_py_calls);
46634665
STACK_SHRINK(argcount);
46644666
for (int i = 0; i < argcount; i++) {
46654667
new_frame->localsplus[i] = stack_pointer[i];
@@ -4690,6 +4692,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
46904692
if (new_frame == NULL) {
46914693
goto error;
46924694
}
4695+
CALL_STAT_INC(inlined_py_calls);
46934696
STACK_SHRINK(argcount);
46944697
for (int i = 0; i < argcount; i++) {
46954698
new_frame->localsplus[i] = stack_pointer[i];
@@ -4708,7 +4711,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
47084711
_PyFrame_SetStackPointer(frame, stack_pointer);
47094712
new_frame->previous = frame;
47104713
frame = cframe.current_frame = new_frame;
4711-
CALL_STAT_INC(inlined_py_calls);
47124714
goto start_frame;
47134715
}
47144716

@@ -6078,6 +6080,7 @@ _PyEvalFramePushAndInit(PyThreadState *tstate, PyFunctionObject *func,
60786080
{
60796081
PyCodeObject * code = (PyCodeObject *)func->func_code;
60806082
size_t size = code->co_nlocalsplus + code->co_stacksize + FRAME_SPECIALS_SIZE;
6083+
CALL_STAT_INC(frames_pushed);
60816084
InterpreterFrame *frame = _PyThreadState_BumpFramePointer(tstate, size);
60826085
if (frame == NULL) {
60836086
goto fail;

Python/frame.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11

22
#include "Python.h"
33
#include "frameobject.h"
4+
#include "pycore_code.h" // stats
45
#include "pycore_frame.h"
56
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
67
#include "opcode.h"
@@ -113,6 +114,7 @@ _PyFrame_Push(PyThreadState *tstate, PyFunctionObject *func)
113114
{
114115
PyCodeObject *code = (PyCodeObject *)func->func_code;
115116
size_t size = code->co_nlocalsplus + code->co_stacksize + FRAME_SPECIALS_SIZE;
117+
CALL_STAT_INC(frames_pushed);
116118
InterpreterFrame *new_frame = _PyThreadState_BumpFramePointer(tstate, size);
117119
if (new_frame == NULL) {
118120
return NULL;

Python/pystate.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include "Python.h"
55
#include "pycore_ceval.h"
6+
#include "pycore_code.h" // stats
67
#include "pycore_frame.h"
78
#include "pycore_initconfig.h"
89
#include "pycore_object.h" // _PyType_InitCache()
@@ -2219,6 +2220,7 @@ _PyThreadState_PushFrame(PyThreadState *tstate, PyFunctionObject *func, PyObject
22192220
int nlocalsplus = code->co_nlocalsplus;
22202221
size_t size = nlocalsplus + code->co_stacksize +
22212222
FRAME_SPECIALS_SIZE;
2223+
CALL_STAT_INC(frames_pushed);
22222224
InterpreterFrame *frame = _PyThreadState_BumpFramePointer(tstate, size);
22232225
if (frame == NULL) {
22242226
return NULL;

Python/specialize.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,8 @@ print_call_stats(FILE *out, CallStats *stats)
169169
{
170170
fprintf(out, "Calls to PyEval_EvalDefault: %" PRIu64 "\n", stats->pyeval_calls);
171171
fprintf(out, "Calls to Python functions inlined: %" PRIu64 "\n", stats->inlined_py_calls);
172+
fprintf(out, "Frames pushed: %" PRIu64 "\n", stats->frames_pushed);
173+
fprintf(out, "Frame objects created: %" PRIu64 "\n", stats->frame_objects_created);
172174
}
173175

174176
static void

Tools/scripts/summarize_stats.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ def main():
106106
for key, value in stats.items():
107107
if "Calls to" in key:
108108
print(f" {key}: {value} {100*value/total:0.1f}%")
109+
for key, value in stats.items():
110+
if key.startswith("Frame"):
111+
print(f" {key}: {value} {100*value/total:0.1f}%")
109112
print("Object stats:")
110113
total = stats.get("Object new values")
111114
for key, value in stats.items():

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy