[Python-checkins] bpo-46072: Add some frame stats. (GH-31060)
markshannon
webhook-mailer at python.org
Wed Feb 2 06:02:01 EST 2022
https://github.com/python/cpython/commit/187930f74c44e460ba09c60ba5d9bb4fac543d8f
commit: 187930f74c44e460ba09c60ba5d9bb4fac543d8f
branch: main
author: Mark Shannon <mark at hotpy.org>
committer: markshannon <mark at hotpy.org>
date: 2022-02-02T11:01:33Z
summary:
bpo-46072: Add some frame stats. (GH-31060)
files:
M Include/internal/pycore_code.h
M Objects/frameobject.c
M Python/ceval.c
M Python/frame.c
M Python/pystate.c
M Python/specialize.c
M Tools/scripts/summarize_stats.py
diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h
index 45c7752112b46..3897ea0ab6a1a 100644
--- a/Include/internal/pycore_code.h
+++ b/Include/internal/pycore_code.h
@@ -303,6 +303,8 @@ typedef struct _opcode_stats {
typedef struct _call_stats {
uint64_t inlined_py_calls;
uint64_t pyeval_calls;
+ uint64_t frames_pushed;
+ uint64_t frame_objects_created;
} CallStats;
typedef struct _object_stats {
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
index 81ad4cc65d150..15da1325d1480 100644
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -794,6 +794,7 @@ init_frame(InterpreterFrame *frame, PyFunctionObject *func, PyObject *locals)
PyFrameObject*
_PyFrame_New_NoTrack(PyCodeObject *code)
{
+ CALL_STAT_INC(frame_objects_created);
int slots = code->co_nlocalsplus + code->co_stacksize;
PyFrameObject *f = PyObject_GC_NewVar(PyFrameObject, &PyFrame_Type, slots);
if (f == NULL) {
diff --git a/Python/ceval.c b/Python/ceval.c
index b69d5aa9d3206..70748e8911f9f 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -2242,6 +2242,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
if (new_frame == NULL) {
goto error;
}
+ CALL_STAT_INC(frames_pushed);
_PyFrame_InitializeSpecials(new_frame, getitem,
NULL, code->co_nlocalsplus);
STACK_SHRINK(2);
@@ -4660,6 +4661,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
if (new_frame == NULL) {
goto error;
}
+ CALL_STAT_INC(inlined_py_calls);
STACK_SHRINK(argcount);
for (int i = 0; i < argcount; i++) {
new_frame->localsplus[i] = stack_pointer[i];
@@ -4690,6 +4692,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
if (new_frame == NULL) {
goto error;
}
+ CALL_STAT_INC(inlined_py_calls);
STACK_SHRINK(argcount);
for (int i = 0; i < argcount; i++) {
new_frame->localsplus[i] = stack_pointer[i];
@@ -4708,7 +4711,6 @@ _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;
}
@@ -6078,6 +6080,7 @@ _PyEvalFramePushAndInit(PyThreadState *tstate, PyFunctionObject *func,
{
PyCodeObject * code = (PyCodeObject *)func->func_code;
size_t size = code->co_nlocalsplus + code->co_stacksize + FRAME_SPECIALS_SIZE;
+ CALL_STAT_INC(frames_pushed);
InterpreterFrame *frame = _PyThreadState_BumpFramePointer(tstate, size);
if (frame == NULL) {
goto fail;
diff --git a/Python/frame.c b/Python/frame.c
index 771de7583be79..ca7c5f9c94e07 100644
--- a/Python/frame.c
+++ b/Python/frame.c
@@ -1,6 +1,7 @@
#include "Python.h"
#include "frameobject.h"
+#include "pycore_code.h" // stats
#include "pycore_frame.h"
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
#include "opcode.h"
@@ -113,6 +114,7 @@ _PyFrame_Push(PyThreadState *tstate, PyFunctionObject *func)
{
PyCodeObject *code = (PyCodeObject *)func->func_code;
size_t size = code->co_nlocalsplus + code->co_stacksize + FRAME_SPECIALS_SIZE;
+ CALL_STAT_INC(frames_pushed);
InterpreterFrame *new_frame = _PyThreadState_BumpFramePointer(tstate, size);
if (new_frame == NULL) {
return NULL;
diff --git a/Python/pystate.c b/Python/pystate.c
index 4378d78a8b781..77467944e2afb 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -3,6 +3,7 @@
#include "Python.h"
#include "pycore_ceval.h"
+#include "pycore_code.h" // stats
#include "pycore_frame.h"
#include "pycore_initconfig.h"
#include "pycore_object.h" // _PyType_InitCache()
@@ -2219,6 +2220,7 @@ _PyThreadState_PushFrame(PyThreadState *tstate, PyFunctionObject *func, PyObject
int nlocalsplus = code->co_nlocalsplus;
size_t size = nlocalsplus + code->co_stacksize +
FRAME_SPECIALS_SIZE;
+ CALL_STAT_INC(frames_pushed);
InterpreterFrame *frame = _PyThreadState_BumpFramePointer(tstate, size);
if (frame == NULL) {
return NULL;
diff --git a/Python/specialize.c b/Python/specialize.c
index 5771a41dcfd2c..9290fbe823956 100644
--- a/Python/specialize.c
+++ b/Python/specialize.c
@@ -169,6 +169,8 @@ 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);
+ fprintf(out, "Frames pushed: %" PRIu64 "\n", stats->frames_pushed);
+ fprintf(out, "Frame objects created: %" PRIu64 "\n", stats->frame_objects_created);
}
static void
diff --git a/Tools/scripts/summarize_stats.py b/Tools/scripts/summarize_stats.py
index 2761dcb50985b..319b251c854a8 100644
--- a/Tools/scripts/summarize_stats.py
+++ b/Tools/scripts/summarize_stats.py
@@ -106,6 +106,9 @@ def main():
for key, value in stats.items():
if "Calls to" in key:
print(f" {key}: {value} {100*value/total:0.1f}%")
+ for key, value in stats.items():
+ if key.startswith("Frame"):
+ print(f" {key}: {value} {100*value/total:0.1f}%")
print("Object stats:")
total = stats.get("Object new values")
for key, value in stats.items():
More information about the Python-checkins
mailing list