mirror of
https://github.com/python/cpython.git
synced 2025-08-22 17:55:18 +00:00
bpo-46072: Add some frame stats. (GH-31060)
This commit is contained in:
parent
a05866ce3e
commit
187930f74c
7 changed files with 16 additions and 1 deletions
|
@ -303,6 +303,8 @@ typedef struct _opcode_stats {
|
||||||
typedef struct _call_stats {
|
typedef struct _call_stats {
|
||||||
uint64_t inlined_py_calls;
|
uint64_t inlined_py_calls;
|
||||||
uint64_t pyeval_calls;
|
uint64_t pyeval_calls;
|
||||||
|
uint64_t frames_pushed;
|
||||||
|
uint64_t frame_objects_created;
|
||||||
} CallStats;
|
} CallStats;
|
||||||
|
|
||||||
typedef struct _object_stats {
|
typedef struct _object_stats {
|
||||||
|
|
|
@ -794,6 +794,7 @@ init_frame(InterpreterFrame *frame, PyFunctionObject *func, PyObject *locals)
|
||||||
PyFrameObject*
|
PyFrameObject*
|
||||||
_PyFrame_New_NoTrack(PyCodeObject *code)
|
_PyFrame_New_NoTrack(PyCodeObject *code)
|
||||||
{
|
{
|
||||||
|
CALL_STAT_INC(frame_objects_created);
|
||||||
int slots = code->co_nlocalsplus + code->co_stacksize;
|
int slots = code->co_nlocalsplus + code->co_stacksize;
|
||||||
PyFrameObject *f = PyObject_GC_NewVar(PyFrameObject, &PyFrame_Type, slots);
|
PyFrameObject *f = PyObject_GC_NewVar(PyFrameObject, &PyFrame_Type, slots);
|
||||||
if (f == NULL) {
|
if (f == NULL) {
|
||||||
|
|
|
@ -2242,6 +2242,7 @@ handle_eval_breaker:
|
||||||
if (new_frame == NULL) {
|
if (new_frame == NULL) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
CALL_STAT_INC(frames_pushed);
|
||||||
_PyFrame_InitializeSpecials(new_frame, getitem,
|
_PyFrame_InitializeSpecials(new_frame, getitem,
|
||||||
NULL, code->co_nlocalsplus);
|
NULL, code->co_nlocalsplus);
|
||||||
STACK_SHRINK(2);
|
STACK_SHRINK(2);
|
||||||
|
@ -4660,6 +4661,7 @@ handle_eval_breaker:
|
||||||
if (new_frame == NULL) {
|
if (new_frame == NULL) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
CALL_STAT_INC(inlined_py_calls);
|
||||||
STACK_SHRINK(argcount);
|
STACK_SHRINK(argcount);
|
||||||
for (int i = 0; i < argcount; i++) {
|
for (int i = 0; i < argcount; i++) {
|
||||||
new_frame->localsplus[i] = stack_pointer[i];
|
new_frame->localsplus[i] = stack_pointer[i];
|
||||||
|
@ -4690,6 +4692,7 @@ handle_eval_breaker:
|
||||||
if (new_frame == NULL) {
|
if (new_frame == NULL) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
CALL_STAT_INC(inlined_py_calls);
|
||||||
STACK_SHRINK(argcount);
|
STACK_SHRINK(argcount);
|
||||||
for (int i = 0; i < argcount; i++) {
|
for (int i = 0; i < argcount; i++) {
|
||||||
new_frame->localsplus[i] = stack_pointer[i];
|
new_frame->localsplus[i] = stack_pointer[i];
|
||||||
|
@ -4708,7 +4711,6 @@ handle_eval_breaker:
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
new_frame->previous = frame;
|
new_frame->previous = frame;
|
||||||
frame = cframe.current_frame = new_frame;
|
frame = cframe.current_frame = new_frame;
|
||||||
CALL_STAT_INC(inlined_py_calls);
|
|
||||||
goto start_frame;
|
goto start_frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6078,6 +6080,7 @@ _PyEvalFramePushAndInit(PyThreadState *tstate, PyFunctionObject *func,
|
||||||
{
|
{
|
||||||
PyCodeObject * code = (PyCodeObject *)func->func_code;
|
PyCodeObject * code = (PyCodeObject *)func->func_code;
|
||||||
size_t size = code->co_nlocalsplus + code->co_stacksize + FRAME_SPECIALS_SIZE;
|
size_t size = code->co_nlocalsplus + code->co_stacksize + FRAME_SPECIALS_SIZE;
|
||||||
|
CALL_STAT_INC(frames_pushed);
|
||||||
InterpreterFrame *frame = _PyThreadState_BumpFramePointer(tstate, size);
|
InterpreterFrame *frame = _PyThreadState_BumpFramePointer(tstate, size);
|
||||||
if (frame == NULL) {
|
if (frame == NULL) {
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include "frameobject.h"
|
#include "frameobject.h"
|
||||||
|
#include "pycore_code.h" // stats
|
||||||
#include "pycore_frame.h"
|
#include "pycore_frame.h"
|
||||||
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
|
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
|
||||||
#include "opcode.h"
|
#include "opcode.h"
|
||||||
|
@ -113,6 +114,7 @@ _PyFrame_Push(PyThreadState *tstate, PyFunctionObject *func)
|
||||||
{
|
{
|
||||||
PyCodeObject *code = (PyCodeObject *)func->func_code;
|
PyCodeObject *code = (PyCodeObject *)func->func_code;
|
||||||
size_t size = code->co_nlocalsplus + code->co_stacksize + FRAME_SPECIALS_SIZE;
|
size_t size = code->co_nlocalsplus + code->co_stacksize + FRAME_SPECIALS_SIZE;
|
||||||
|
CALL_STAT_INC(frames_pushed);
|
||||||
InterpreterFrame *new_frame = _PyThreadState_BumpFramePointer(tstate, size);
|
InterpreterFrame *new_frame = _PyThreadState_BumpFramePointer(tstate, size);
|
||||||
if (new_frame == NULL) {
|
if (new_frame == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include "pycore_ceval.h"
|
#include "pycore_ceval.h"
|
||||||
|
#include "pycore_code.h" // stats
|
||||||
#include "pycore_frame.h"
|
#include "pycore_frame.h"
|
||||||
#include "pycore_initconfig.h"
|
#include "pycore_initconfig.h"
|
||||||
#include "pycore_object.h" // _PyType_InitCache()
|
#include "pycore_object.h" // _PyType_InitCache()
|
||||||
|
@ -2219,6 +2220,7 @@ _PyThreadState_PushFrame(PyThreadState *tstate, PyFunctionObject *func, PyObject
|
||||||
int nlocalsplus = code->co_nlocalsplus;
|
int nlocalsplus = code->co_nlocalsplus;
|
||||||
size_t size = nlocalsplus + code->co_stacksize +
|
size_t size = nlocalsplus + code->co_stacksize +
|
||||||
FRAME_SPECIALS_SIZE;
|
FRAME_SPECIALS_SIZE;
|
||||||
|
CALL_STAT_INC(frames_pushed);
|
||||||
InterpreterFrame *frame = _PyThreadState_BumpFramePointer(tstate, size);
|
InterpreterFrame *frame = _PyThreadState_BumpFramePointer(tstate, size);
|
||||||
if (frame == NULL) {
|
if (frame == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -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 PyEval_EvalDefault: %" PRIu64 "\n", stats->pyeval_calls);
|
||||||
fprintf(out, "Calls to Python functions inlined: %" PRIu64 "\n", stats->inlined_py_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
|
static void
|
||||||
|
|
|
@ -106,6 +106,9 @@ def main():
|
||||||
for key, value in stats.items():
|
for key, value in stats.items():
|
||||||
if "Calls to" in key:
|
if "Calls to" in key:
|
||||||
print(f" {key}: {value} {100*value/total:0.1f}%")
|
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:")
|
print("Object stats:")
|
||||||
total = stats.get("Object new values")
|
total = stats.get("Object new values")
|
||||||
for key, value in stats.items():
|
for key, value in stats.items():
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue