diff -r f44f44b14dfc Modules/_lsprof.c --- a/Modules/_lsprof.c Fri Jan 20 08:35:18 2017 +0200 +++ b/Modules/_lsprof.c Fri Jan 20 18:02:02 2017 +0200 @@ -2,6 +2,12 @@ #include "frameobject.h" #include "rotatingtree.h" +/*[clinic input] +module _lsprof +class _lsprof.Profiler "ProfilerObject *" "&PyProfiler_Type" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=dea500b5ae122746]*/ + /*** Selection of a high-precision timer ***/ #ifdef MS_WINDOWS @@ -601,46 +607,47 @@ static int statsForEntry(rotating_node_t return err; } -PyDoc_STRVAR(getstats_doc, "\ -getstats() -> list of profiler_entry objects\n\ -\n\ -Return all information collected by the profiler.\n\ -Each profiler_entry is a tuple-like object with the\n\ -following attributes:\n\ -\n\ - code code object\n\ - callcount how many times this was called\n\ - reccallcount how many times called recursively\n\ - totaltime total time in this entry\n\ - inlinetime inline time in this entry (not in subcalls)\n\ - calls details of the calls\n\ -\n\ -The calls attribute is either None or a list of\n\ -profiler_subentry objects:\n\ -\n\ - code called code object\n\ - callcount how many times this is called\n\ - reccallcount how many times this is called recursively\n\ - totaltime total time spent in this call\n\ - inlinetime inline time (not in further subcalls)\n\ -"); -static PyObject* -profiler_getstats(ProfilerObject *pObj, PyObject* noarg) +/*[clinic input] +_lsprof.Profiler.getstats + +Return all information collected by the profiler. + +Each profiler_entry is a tuple-like object with the following attributes: + + code code object + callcount how many times this was called + reccallcount how many times called recursively + totaltime total time in this entry + inlinetime inline time in this entry (not in subcalls) + calls details of the calls + +The calls attribute is either None or a list of profiler_subentry objects: + + code called code object + callcount how many times this is called + reccallcount how many times this is called recursively + totaltime total time spent in this call + inlinetime inline time (not in further subcalls) +[clinic start generated code]*/ + +static PyObject * +_lsprof_Profiler_getstats_impl(ProfilerObject *self) +/*[clinic end generated code: output=9461b451e9ef0f24 input=a6d5ede1f4cb3f71]*/ { statscollector_t collect; - if (pending_exception(pObj)) + if (pending_exception(self)) return NULL; - if (!pObj->externalTimer) + if (!self->externalTimer) collect.factor = hpTimerUnit(); - else if (pObj->externalTimerUnit > 0.0) - collect.factor = pObj->externalTimerUnit; + else if (self->externalTimerUnit > 0.0) + collect.factor = self->externalTimerUnit; else collect.factor = 1.0 / DOUBLE_TIMER_PRECISION; collect.list = PyList_New(0); if (collect.list == NULL) return NULL; - if (RotatingTree_Enum(pObj->profilerEntries, statsForEntry, &collect) + if (RotatingTree_Enum(self->profilerEntries, statsForEntry, &collect) != 0) { Py_DECREF(collect.list); return NULL; @@ -669,31 +676,32 @@ setBuiltins(ProfilerObject *pObj, int nv return 0; } -PyDoc_STRVAR(enable_doc, "\ -enable(subcalls=True, builtins=True)\n\ -\n\ -Start collecting profiling information.\n\ -If 'subcalls' is True, also records for each function\n\ -statistics separated according to its current caller.\n\ -If 'builtins' is True, records the time spent in\n\ -built-in functions separately from their caller.\n\ -"); -static PyObject* -profiler_enable(ProfilerObject *self, PyObject *args, PyObject *kwds) +/*[clinic input] +_lsprof.Profiler.enable + + subcalls: int = -1 + builtins: int = -1 + / + +Start collecting profiling information. + +If 'subcalls' is True, also records for each function +statistics separated according to its current caller. +If 'builtins' is True, records the time spent in +built-in functions separately from their caller. +[clinic start generated code]*/ + +static PyObject * +_lsprof_Profiler_enable_impl(ProfilerObject *self, int subcalls, + int builtins) +/*[clinic end generated code: output=1e747f9dc1edd571 input=7443f0f3799d770a]*/ { - int subcalls = -1; - int builtins = -1; - static char *kwlist[] = {"subcalls", "builtins", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ii:enable", - kwlist, &subcalls, &builtins)) - return NULL; if (setSubcalls(self, subcalls) < 0 || setBuiltins(self, builtins) < 0) return NULL; PyEval_SetProfile(profiler_callback, (PyObject*)self); self->flags |= POF_ENABLED; - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } static void @@ -712,36 +720,38 @@ flush_unmatched(ProfilerObject *pObj) } -PyDoc_STRVAR(disable_doc, "\ -disable()\n\ -\n\ -Stop collecting profiling information.\n\ -"); -static PyObject* -profiler_disable(ProfilerObject *self, PyObject* noarg) +/*[clinic input] +_lsprof.Profiler.disable + +Stop collecting profiling information. +[clinic start generated code]*/ + +static PyObject * +_lsprof_Profiler_disable_impl(ProfilerObject *self) +/*[clinic end generated code: output=838cffef7f651870 input=05700b3fc68d1f50]*/ { self->flags &= ~POF_ENABLED; PyEval_SetProfile(NULL, NULL); flush_unmatched(self); if (pending_exception(self)) return NULL; - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } -PyDoc_STRVAR(clear_doc, "\ -clear()\n\ -\n\ -Clear all profiling information collected so far.\n\ -"); -static PyObject* -profiler_clear(ProfilerObject *pObj, PyObject* noarg) +/*[clinic input] +_lsprof.Profiler.clear + +Clear all profiling information collected so far. +[clinic start generated code]*/ + +static PyObject * +_lsprof_Profiler_clear_impl(ProfilerObject *self) +/*[clinic end generated code: output=dd1c668fb84b1335 input=fbe1f88c28be4f98]*/ { - clearEntries(pObj); - Py_INCREF(Py_None); - return Py_None; + clearEntries(self); + Py_RETURN_NONE; } static void @@ -755,51 +765,46 @@ profiler_dealloc(ProfilerObject *op) Py_TYPE(op)->tp_free(op); } +/*[clinic input] +_lsprof.Profiler.__init__ + + timer: object = NULL + timeunit: double = 0.0 + subcalls: int(c_default="1") = True + builtins: int(c_default="1") = True + / + +Builds a profiler object using the specified timer function. + +The default timer is a fast built-in one based on real time. +For custom timer functions returning integers, timeunit can +be a float specifying a scale (i.e. how long each integer unit +is, in seconds). +[clinic start generated code]*/ + static int -profiler_init(ProfilerObject *pObj, PyObject *args, PyObject *kw) +_lsprof_Profiler___init___impl(ProfilerObject *self, PyObject *timer, + double timeunit, int subcalls, int builtins) +/*[clinic end generated code: output=ab5498359fd34283 input=310726c90ffbcfa1]*/ { - PyObject *timer = NULL; - double timeunit = 0.0; - int subcalls = 1; - int builtins = 1; - static char *kwlist[] = {"timer", "timeunit", - "subcalls", "builtins", 0}; - - if (!PyArg_ParseTupleAndKeywords(args, kw, "|Odii:Profiler", kwlist, - &timer, &timeunit, - &subcalls, &builtins)) + if (setSubcalls(self, subcalls) < 0 || setBuiltins(self, builtins) < 0) return -1; - - if (setSubcalls(pObj, subcalls) < 0 || setBuiltins(pObj, builtins) < 0) - return -1; - pObj->externalTimerUnit = timeunit; + self->externalTimerUnit = timeunit; Py_XINCREF(timer); - Py_XSETREF(pObj->externalTimer, timer); + Py_XSETREF(self->externalTimer, timer); return 0; } +#include "clinic/_lsprof.c.h" + static PyMethodDef profiler_methods[] = { - {"getstats", (PyCFunction)profiler_getstats, - METH_NOARGS, getstats_doc}, - {"enable", (PyCFunction)profiler_enable, - METH_VARARGS | METH_KEYWORDS, enable_doc}, - {"disable", (PyCFunction)profiler_disable, - METH_NOARGS, disable_doc}, - {"clear", (PyCFunction)profiler_clear, - METH_NOARGS, clear_doc}, + _LSPROF_PROFILER_GETSTATS_METHODDEF + _LSPROF_PROFILER_ENABLE_METHODDEF + _LSPROF_PROFILER_DISABLE_METHODDEF + _LSPROF_PROFILER_CLEAR_METHODDEF {NULL, NULL} }; -PyDoc_STRVAR(profiler_doc, "\ -Profiler(custom_timer=None, time_unit=None, subcalls=True, builtins=True)\n\ -\n\ - Builds a profiler object using the specified timer function.\n\ - The default timer is a fast built-in one based on real time.\n\ - For custom timer functions returning integers, time_unit can\n\ - be a float specifying a scale (i.e. how long each integer unit\n\ - is, in seconds).\n\ -"); - static PyTypeObject PyProfiler_Type = { PyVarObject_HEAD_INIT(NULL, 0) "_lsprof.Profiler", /* tp_name */ @@ -821,7 +826,7 @@ static PyTypeObject PyProfiler_Type = { 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - profiler_doc, /* tp_doc */ + _lsprof_Profiler___init____doc__, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ @@ -836,7 +841,7 @@ static PyTypeObject PyProfiler_Type = { 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ - (initproc)profiler_init, /* tp_init */ + _lsprof_Profiler___init__, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ PyType_GenericNew, /* tp_new */ PyObject_Del, /* tp_free */ diff -r f44f44b14dfc Modules/clinic/_lsprof.c.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Modules/clinic/_lsprof.c.h Fri Jan 20 18:02:02 2017 +0200 @@ -0,0 +1,152 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +PyDoc_STRVAR(_lsprof_Profiler_getstats__doc__, +"getstats($self, /)\n" +"--\n" +"\n" +"Return all information collected by the profiler.\n" +"\n" +"Each profiler_entry is a tuple-like object with the following attributes:\n" +"\n" +" code code object\n" +" callcount how many times this was called\n" +" reccallcount how many times called recursively\n" +" totaltime total time in this entry\n" +" inlinetime inline time in this entry (not in subcalls)\n" +" calls details of the calls\n" +"\n" +"The calls attribute is either None or a list of profiler_subentry objects:\n" +"\n" +" code called code object\n" +" callcount how many times this is called\n" +" reccallcount how many times this is called recursively\n" +" totaltime total time spent in this call\n" +" inlinetime inline time (not in further subcalls)"); + +#define _LSPROF_PROFILER_GETSTATS_METHODDEF \ + {"getstats", (PyCFunction)_lsprof_Profiler_getstats, METH_NOARGS, _lsprof_Profiler_getstats__doc__}, + +static PyObject * +_lsprof_Profiler_getstats_impl(ProfilerObject *self); + +static PyObject * +_lsprof_Profiler_getstats(ProfilerObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _lsprof_Profiler_getstats_impl(self); +} + +PyDoc_STRVAR(_lsprof_Profiler_enable__doc__, +"enable($self, subcalls=-1, builtins=-1, /)\n" +"--\n" +"\n" +"Start collecting profiling information.\n" +"\n" +"If \'subcalls\' is True, also records for each function\n" +"statistics separated according to its current caller.\n" +"If \'builtins\' is True, records the time spent in\n" +"built-in functions separately from their caller."); + +#define _LSPROF_PROFILER_ENABLE_METHODDEF \ + {"enable", (PyCFunction)_lsprof_Profiler_enable, METH_FASTCALL, _lsprof_Profiler_enable__doc__}, + +static PyObject * +_lsprof_Profiler_enable_impl(ProfilerObject *self, int subcalls, + int builtins); + +static PyObject * +_lsprof_Profiler_enable(ProfilerObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + int subcalls = -1; + int builtins = -1; + + if (!_PyArg_ParseStack(args, nargs, "|ii:enable", + &subcalls, &builtins)) { + goto exit; + } + + if (!_PyArg_NoStackKeywords("enable", kwnames)) { + goto exit; + } + return_value = _lsprof_Profiler_enable_impl(self, subcalls, builtins); + +exit: + return return_value; +} + +PyDoc_STRVAR(_lsprof_Profiler_disable__doc__, +"disable($self, /)\n" +"--\n" +"\n" +"Stop collecting profiling information."); + +#define _LSPROF_PROFILER_DISABLE_METHODDEF \ + {"disable", (PyCFunction)_lsprof_Profiler_disable, METH_NOARGS, _lsprof_Profiler_disable__doc__}, + +static PyObject * +_lsprof_Profiler_disable_impl(ProfilerObject *self); + +static PyObject * +_lsprof_Profiler_disable(ProfilerObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _lsprof_Profiler_disable_impl(self); +} + +PyDoc_STRVAR(_lsprof_Profiler_clear__doc__, +"clear($self, /)\n" +"--\n" +"\n" +"Clear all profiling information collected so far."); + +#define _LSPROF_PROFILER_CLEAR_METHODDEF \ + {"clear", (PyCFunction)_lsprof_Profiler_clear, METH_NOARGS, _lsprof_Profiler_clear__doc__}, + +static PyObject * +_lsprof_Profiler_clear_impl(ProfilerObject *self); + +static PyObject * +_lsprof_Profiler_clear(ProfilerObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _lsprof_Profiler_clear_impl(self); +} + +PyDoc_STRVAR(_lsprof_Profiler___init____doc__, +"Profiler(timer=None, timeunit=0.0, subcalls=True, builtins=True, /)\n" +"--\n" +"\n" +"Builds a profiler object using the specified timer function.\n" +"\n" +"The default timer is a fast built-in one based on real time.\n" +"For custom timer functions returning integers, timeunit can\n" +"be a float specifying a scale (i.e. how long each integer unit\n" +"is, in seconds)."); + +static int +_lsprof_Profiler___init___impl(ProfilerObject *self, PyObject *timer, + double timeunit, int subcalls, int builtins); + +static int +_lsprof_Profiler___init__(PyObject *self, PyObject *args, PyObject *kwargs) +{ + int return_value = -1; + PyObject *timer = NULL; + double timeunit = 0.0; + int subcalls = 1; + int builtins = 1; + + if ((Py_TYPE(self) == &PyProfiler_Type) && + !_PyArg_NoKeywords("Profiler", kwargs)) { + goto exit; + } + if (!PyArg_ParseTuple(args, "|Odii:Profiler", + &timer, &timeunit, &subcalls, &builtins)) { + goto exit; + } + return_value = _lsprof_Profiler___init___impl((ProfilerObject *)self, timer, timeunit, subcalls, builtins); + +exit: + return return_value; +} +/*[clinic end generated code: output=205f6aa40ac0e5b7 input=a9049054013a1b77]*/