Remove CALL_PROFILE special build
Issue #28799: * Remove the PyEval_GetCallStats() function. * Deprecate the untested and undocumented sys.callstats() function. * Remove the CALL_PROFILE special build Use the sys.setprofile() function, cProfile or profile module to profile function calls.
This commit is contained in:
parent
214678e44b
commit
048afd98b3
|
@ -1147,46 +1147,6 @@ Python-level trace functions in previous versions.
|
||||||
:c:func:`PyEval_SetProfile`, except the tracing function does receive line-number
|
:c:func:`PyEval_SetProfile`, except the tracing function does receive line-number
|
||||||
events.
|
events.
|
||||||
|
|
||||||
.. c:function:: PyObject* PyEval_GetCallStats(PyObject *self)
|
|
||||||
|
|
||||||
Return a tuple of function call counts. There are constants defined for the
|
|
||||||
positions within the tuple:
|
|
||||||
|
|
||||||
+-------------------------------+-------+
|
|
||||||
| Name | Value |
|
|
||||||
+===============================+=======+
|
|
||||||
| :const:`PCALL_ALL` | 0 |
|
|
||||||
+-------------------------------+-------+
|
|
||||||
| :const:`PCALL_FUNCTION` | 1 |
|
|
||||||
+-------------------------------+-------+
|
|
||||||
| :const:`PCALL_FAST_FUNCTION` | 2 |
|
|
||||||
+-------------------------------+-------+
|
|
||||||
| :const:`PCALL_FASTER_FUNCTION`| 3 |
|
|
||||||
+-------------------------------+-------+
|
|
||||||
| :const:`PCALL_METHOD` | 4 |
|
|
||||||
+-------------------------------+-------+
|
|
||||||
| :const:`PCALL_BOUND_METHOD` | 5 |
|
|
||||||
+-------------------------------+-------+
|
|
||||||
| :const:`PCALL_CFUNCTION` | 6 |
|
|
||||||
+-------------------------------+-------+
|
|
||||||
| :const:`PCALL_TYPE` | 7 |
|
|
||||||
+-------------------------------+-------+
|
|
||||||
| :const:`PCALL_GENERATOR` | 8 |
|
|
||||||
+-------------------------------+-------+
|
|
||||||
| :const:`PCALL_OTHER` | 9 |
|
|
||||||
+-------------------------------+-------+
|
|
||||||
| :const:`PCALL_POP` | 10 |
|
|
||||||
+-------------------------------+-------+
|
|
||||||
|
|
||||||
:const:`PCALL_FAST_FUNCTION` means no argument tuple needs to be created.
|
|
||||||
:const:`PCALL_FASTER_FUNCTION` means that the fast-path frame setup code is used.
|
|
||||||
|
|
||||||
If there is a method call where the call can be optimized by changing
|
|
||||||
the argument tuple and calling the function directly, it gets recorded
|
|
||||||
twice.
|
|
||||||
|
|
||||||
This function is only present if Python is compiled with :const:`CALL_PROFILE`
|
|
||||||
defined.
|
|
||||||
|
|
||||||
.. _advanced-debugging:
|
.. _advanced-debugging:
|
||||||
|
|
||||||
|
|
|
@ -120,7 +120,6 @@ PyAPI_DATA(int) _Py_CheckRecursionLimit;
|
||||||
PyAPI_FUNC(const char *) PyEval_GetFuncName(PyObject *);
|
PyAPI_FUNC(const char *) PyEval_GetFuncName(PyObject *);
|
||||||
PyAPI_FUNC(const char *) PyEval_GetFuncDesc(PyObject *);
|
PyAPI_FUNC(const char *) PyEval_GetFuncDesc(PyObject *);
|
||||||
|
|
||||||
PyAPI_FUNC(PyObject *) PyEval_GetCallStats(PyObject *);
|
|
||||||
PyAPI_FUNC(PyObject *) PyEval_EvalFrame(struct _frame *);
|
PyAPI_FUNC(PyObject *) PyEval_EvalFrame(struct _frame *);
|
||||||
PyAPI_FUNC(PyObject *) PyEval_EvalFrameEx(struct _frame *f, int exc);
|
PyAPI_FUNC(PyObject *) PyEval_EvalFrameEx(struct _frame *f, int exc);
|
||||||
#ifndef Py_LIMITED_API
|
#ifndef Py_LIMITED_API
|
||||||
|
|
|
@ -10,6 +10,11 @@ What's New in Python 3.7.0 alpha 1
|
||||||
Core and Builtins
|
Core and Builtins
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
- Issue #28799: Remove the ``PyEval_GetCallStats()`` function and deprecate
|
||||||
|
the untested and undocumented ``sys.callstats()`` function. Remove the
|
||||||
|
``CALL_PROFILE`` special build: use the :func:`sys.setprofile` function,
|
||||||
|
:mod:`cProfile` or :mod:`profile` to profile function calls.
|
||||||
|
|
||||||
- Issue #12844: More than 255 arguments can now be passed to a function.
|
- Issue #12844: More than 255 arguments can now be passed to a function.
|
||||||
|
|
||||||
- Issue #28782: Fix a bug in the implementation ``yield from`` when checking
|
- Issue #28782: Fix a bug in the implementation ``yield from`` when checking
|
||||||
|
|
|
@ -83,63 +83,6 @@ static long dxp[256];
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Function call profile */
|
|
||||||
#ifdef CALL_PROFILE
|
|
||||||
#define PCALL_NUM 11
|
|
||||||
static int pcall[PCALL_NUM];
|
|
||||||
|
|
||||||
#define PCALL_ALL 0
|
|
||||||
#define PCALL_FUNCTION 1
|
|
||||||
#define PCALL_FAST_FUNCTION 2
|
|
||||||
#define PCALL_FASTER_FUNCTION 3
|
|
||||||
#define PCALL_METHOD 4
|
|
||||||
#define PCALL_BOUND_METHOD 5
|
|
||||||
#define PCALL_CFUNCTION 6
|
|
||||||
#define PCALL_TYPE 7
|
|
||||||
#define PCALL_GENERATOR 8
|
|
||||||
#define PCALL_OTHER 9
|
|
||||||
#define PCALL_POP 10
|
|
||||||
|
|
||||||
/* Notes about the statistics
|
|
||||||
|
|
||||||
PCALL_FAST stats
|
|
||||||
|
|
||||||
FAST_FUNCTION means no argument tuple needs to be created.
|
|
||||||
FASTER_FUNCTION means that the fast-path frame setup code is used.
|
|
||||||
|
|
||||||
If there is a method call where the call can be optimized by changing
|
|
||||||
the argument tuple and calling the function directly, it gets recorded
|
|
||||||
twice.
|
|
||||||
|
|
||||||
As a result, the relationship among the statistics appears to be
|
|
||||||
PCALL_ALL == PCALL_FUNCTION + PCALL_METHOD - PCALL_BOUND_METHOD +
|
|
||||||
PCALL_CFUNCTION + PCALL_TYPE + PCALL_GENERATOR + PCALL_OTHER
|
|
||||||
PCALL_FUNCTION > PCALL_FAST_FUNCTION > PCALL_FASTER_FUNCTION
|
|
||||||
PCALL_METHOD > PCALL_BOUND_METHOD
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define PCALL(POS) pcall[POS]++
|
|
||||||
|
|
||||||
PyObject *
|
|
||||||
PyEval_GetCallStats(PyObject *self)
|
|
||||||
{
|
|
||||||
return Py_BuildValue("iiiiiiiiiii",
|
|
||||||
pcall[0], pcall[1], pcall[2], pcall[3],
|
|
||||||
pcall[4], pcall[5], pcall[6], pcall[7],
|
|
||||||
pcall[8], pcall[9], pcall[10]);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#define PCALL(O)
|
|
||||||
|
|
||||||
PyObject *
|
|
||||||
PyEval_GetCallStats(PyObject *self)
|
|
||||||
{
|
|
||||||
Py_INCREF(Py_None);
|
|
||||||
return Py_None;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef WITH_THREAD
|
#ifdef WITH_THREAD
|
||||||
#define GIL_REQUEST _Py_atomic_load_relaxed(&gil_drop_request)
|
#define GIL_REQUEST _Py_atomic_load_relaxed(&gil_drop_request)
|
||||||
#else
|
#else
|
||||||
|
@ -3278,7 +3221,6 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
|
||||||
PREDICTED(CALL_FUNCTION);
|
PREDICTED(CALL_FUNCTION);
|
||||||
TARGET(CALL_FUNCTION) {
|
TARGET(CALL_FUNCTION) {
|
||||||
PyObject **sp, *res;
|
PyObject **sp, *res;
|
||||||
PCALL(PCALL_ALL);
|
|
||||||
sp = stack_pointer;
|
sp = stack_pointer;
|
||||||
res = call_function(&sp, oparg, NULL);
|
res = call_function(&sp, oparg, NULL);
|
||||||
stack_pointer = sp;
|
stack_pointer = sp;
|
||||||
|
@ -3294,7 +3236,6 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
|
||||||
|
|
||||||
names = POP();
|
names = POP();
|
||||||
assert(PyTuple_CheckExact(names) && PyTuple_GET_SIZE(names) <= oparg);
|
assert(PyTuple_CheckExact(names) && PyTuple_GET_SIZE(names) <= oparg);
|
||||||
PCALL(PCALL_ALL);
|
|
||||||
sp = stack_pointer;
|
sp = stack_pointer;
|
||||||
res = call_function(&sp, oparg, names);
|
res = call_function(&sp, oparg, names);
|
||||||
stack_pointer = sp;
|
stack_pointer = sp;
|
||||||
|
@ -3309,7 +3250,6 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
|
||||||
|
|
||||||
TARGET(CALL_FUNCTION_EX) {
|
TARGET(CALL_FUNCTION_EX) {
|
||||||
PyObject *func, *callargs, *kwargs = NULL, *result;
|
PyObject *func, *callargs, *kwargs = NULL, *result;
|
||||||
PCALL(PCALL_ALL);
|
|
||||||
if (oparg & 0x01) {
|
if (oparg & 0x01) {
|
||||||
kwargs = POP();
|
kwargs = POP();
|
||||||
if (!PyDict_CheckExact(kwargs)) {
|
if (!PyDict_CheckExact(kwargs)) {
|
||||||
|
@ -4099,8 +4039,6 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
|
||||||
* when the generator is resumed. */
|
* when the generator is resumed. */
|
||||||
Py_CLEAR(f->f_back);
|
Py_CLEAR(f->f_back);
|
||||||
|
|
||||||
PCALL(PCALL_GENERATOR);
|
|
||||||
|
|
||||||
/* Create a new generator that owns the ready to run frame
|
/* Create a new generator that owns the ready to run frame
|
||||||
* and return that as the value. */
|
* and return that as the value. */
|
||||||
if (is_coro) {
|
if (is_coro) {
|
||||||
|
@ -4793,8 +4731,6 @@ call_function(PyObject ***pp_stack, Py_ssize_t oparg, PyObject *kwnames)
|
||||||
if (PyCFunction_Check(func)) {
|
if (PyCFunction_Check(func)) {
|
||||||
PyThreadState *tstate = PyThreadState_GET();
|
PyThreadState *tstate = PyThreadState_GET();
|
||||||
|
|
||||||
PCALL(PCALL_CFUNCTION);
|
|
||||||
|
|
||||||
stack = (*pp_stack) - nargs - nkwargs;
|
stack = (*pp_stack) - nargs - nkwargs;
|
||||||
C_TRACE(x, _PyCFunction_FastCallKeywords(func, stack, nargs, kwnames));
|
C_TRACE(x, _PyCFunction_FastCallKeywords(func, stack, nargs, kwnames));
|
||||||
}
|
}
|
||||||
|
@ -4802,8 +4738,6 @@ call_function(PyObject ***pp_stack, Py_ssize_t oparg, PyObject *kwnames)
|
||||||
if (PyMethod_Check(func) && PyMethod_GET_SELF(func) != NULL) {
|
if (PyMethod_Check(func) && PyMethod_GET_SELF(func) != NULL) {
|
||||||
/* optimize access to bound methods */
|
/* optimize access to bound methods */
|
||||||
PyObject *self = PyMethod_GET_SELF(func);
|
PyObject *self = PyMethod_GET_SELF(func);
|
||||||
PCALL(PCALL_METHOD);
|
|
||||||
PCALL(PCALL_BOUND_METHOD);
|
|
||||||
Py_INCREF(self);
|
Py_INCREF(self);
|
||||||
func = PyMethod_GET_FUNCTION(func);
|
func = PyMethod_GET_FUNCTION(func);
|
||||||
Py_INCREF(func);
|
Py_INCREF(func);
|
||||||
|
@ -4835,7 +4769,6 @@ call_function(PyObject ***pp_stack, Py_ssize_t oparg, PyObject *kwnames)
|
||||||
while ((*pp_stack) > pfunc) {
|
while ((*pp_stack) > pfunc) {
|
||||||
w = EXT_POP(*pp_stack);
|
w = EXT_POP(*pp_stack);
|
||||||
Py_DECREF(w);
|
Py_DECREF(w);
|
||||||
PCALL(PCALL_POP);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return x;
|
return x;
|
||||||
|
@ -4860,7 +4793,6 @@ _PyFunction_FastCall(PyCodeObject *co, PyObject **args, Py_ssize_t nargs,
|
||||||
Py_ssize_t i;
|
Py_ssize_t i;
|
||||||
PyObject *result;
|
PyObject *result;
|
||||||
|
|
||||||
PCALL(PCALL_FASTER_FUNCTION);
|
|
||||||
assert(globals != NULL);
|
assert(globals != NULL);
|
||||||
/* XXX Perhaps we should create a specialized
|
/* XXX Perhaps we should create a specialized
|
||||||
PyFrame_New() that doesn't take locals, but does
|
PyFrame_New() that doesn't take locals, but does
|
||||||
|
@ -4906,9 +4838,6 @@ fast_function(PyObject *func, PyObject **stack,
|
||||||
/* kwnames must only contains str strings, no subclass, and all keys must
|
/* kwnames must only contains str strings, no subclass, and all keys must
|
||||||
be unique */
|
be unique */
|
||||||
|
|
||||||
PCALL(PCALL_FUNCTION);
|
|
||||||
PCALL(PCALL_FAST_FUNCTION);
|
|
||||||
|
|
||||||
if (co->co_kwonlyargcount == 0 && nkwargs == 0 &&
|
if (co->co_kwonlyargcount == 0 && nkwargs == 0 &&
|
||||||
co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE))
|
co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE))
|
||||||
{
|
{
|
||||||
|
@ -4971,9 +4900,6 @@ _PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs,
|
||||||
assert(nargs == 0 || args != NULL);
|
assert(nargs == 0 || args != NULL);
|
||||||
assert(kwargs == NULL || PyDict_Check(kwargs));
|
assert(kwargs == NULL || PyDict_Check(kwargs));
|
||||||
|
|
||||||
PCALL(PCALL_FUNCTION);
|
|
||||||
PCALL(PCALL_FAST_FUNCTION);
|
|
||||||
|
|
||||||
if (co->co_kwonlyargcount == 0 &&
|
if (co->co_kwonlyargcount == 0 &&
|
||||||
(kwargs == NULL || PyDict_Size(kwargs) == 0) &&
|
(kwargs == NULL || PyDict_Size(kwargs) == 0) &&
|
||||||
co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE))
|
co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE))
|
||||||
|
@ -5041,23 +4967,6 @@ _PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs,
|
||||||
static PyObject *
|
static PyObject *
|
||||||
do_call_core(PyObject *func, PyObject *callargs, PyObject *kwdict)
|
do_call_core(PyObject *func, PyObject *callargs, PyObject *kwdict)
|
||||||
{
|
{
|
||||||
#ifdef CALL_PROFILE
|
|
||||||
/* At this point, we have to look at the type of func to
|
|
||||||
update the call stats properly. Do it here so as to avoid
|
|
||||||
exposing the call stats machinery outside ceval.c
|
|
||||||
*/
|
|
||||||
if (PyFunction_Check(func))
|
|
||||||
PCALL(PCALL_FUNCTION);
|
|
||||||
else if (PyMethod_Check(func))
|
|
||||||
PCALL(PCALL_METHOD);
|
|
||||||
else if (PyType_Check(func))
|
|
||||||
PCALL(PCALL_TYPE);
|
|
||||||
else if (PyCFunction_Check(func))
|
|
||||||
PCALL(PCALL_CFUNCTION);
|
|
||||||
else
|
|
||||||
PCALL(PCALL_OTHER);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (PyCFunction_Check(func)) {
|
if (PyCFunction_Check(func)) {
|
||||||
PyObject *result;
|
PyObject *result;
|
||||||
PyThreadState *tstate = PyThreadState_GET();
|
PyThreadState *tstate = PyThreadState_GET();
|
||||||
|
|
|
@ -1287,6 +1287,19 @@ a 11-tuple where the entries in the tuple are counts of:\n\
|
||||||
10. Number of stack pops performed by call_function()"
|
10. Number of stack pops performed by call_function()"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
sys_callstats(PyObject *self)
|
||||||
|
{
|
||||||
|
if (PyErr_WarnEx(PyExc_DeprecationWarning,
|
||||||
|
"sys.callstats() has been deprecated in Python 3.7 "
|
||||||
|
"and will be removed in the future", 1) < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
@ -1352,7 +1365,7 @@ Return True if Python is exiting.");
|
||||||
|
|
||||||
static PyMethodDef sys_methods[] = {
|
static PyMethodDef sys_methods[] = {
|
||||||
/* Might as well keep this in alphabetic order */
|
/* Might as well keep this in alphabetic order */
|
||||||
{"callstats", (PyCFunction)PyEval_GetCallStats, METH_NOARGS,
|
{"callstats", (PyCFunction)sys_callstats, METH_NOARGS,
|
||||||
callstats_doc},
|
callstats_doc},
|
||||||
{"_clear_type_cache", sys_clear_type_cache, METH_NOARGS,
|
{"_clear_type_cache", sys_clear_type_cache, METH_NOARGS,
|
||||||
sys_clear_type_cache__doc__},
|
sys_clear_type_cache__doc__},
|
||||||
|
|
Loading…
Reference in New Issue