blob: 66e534f2a843b4f9cd8c7d83e42aa5966704f38a [file] [log] [blame]
Armin Rigoa871ef22006-02-08 12:53:56 +00001#include "Python.h"
Armin Rigoa871ef22006-02-08 12:53:56 +00002#include "frameobject.h"
Armin Rigoa871ef22006-02-08 12:53:56 +00003#include "rotatingtree.h"
4
5#if !defined(HAVE_LONG_LONG)
6#error "This module requires long longs!"
7#endif
8
9/*** Selection of a high-precision timer ***/
10
11#ifdef MS_WINDOWS
12
13#include <windows.h>
14
15static PY_LONG_LONG
16hpTimer(void)
17{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000018 LARGE_INTEGER li;
19 QueryPerformanceCounter(&li);
20 return li.QuadPart;
Armin Rigoa871ef22006-02-08 12:53:56 +000021}
22
23static double
24hpTimerUnit(void)
25{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000026 LARGE_INTEGER li;
27 if (QueryPerformanceFrequency(&li))
28 return 1.0 / li.QuadPart;
29 else
30 return 0.000001; /* unlikely */
Armin Rigoa871ef22006-02-08 12:53:56 +000031}
32
33#else /* !MS_WINDOWS */
34
35#ifndef HAVE_GETTIMEOFDAY
36#error "This module requires gettimeofday() on non-Windows platforms!"
37#endif
38
Armin Rigoa871ef22006-02-08 12:53:56 +000039#include <sys/resource.h>
40#include <sys/times.h>
Armin Rigoa871ef22006-02-08 12:53:56 +000041
42static PY_LONG_LONG
43hpTimer(void)
44{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000045 struct timeval tv;
46 PY_LONG_LONG ret;
Armin Rigoa871ef22006-02-08 12:53:56 +000047#ifdef GETTIMEOFDAY_NO_TZ
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000048 gettimeofday(&tv);
Armin Rigoa871ef22006-02-08 12:53:56 +000049#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000050 gettimeofday(&tv, (struct timezone *)NULL);
Armin Rigoa871ef22006-02-08 12:53:56 +000051#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000052 ret = tv.tv_sec;
53 ret = ret * 1000000 + tv.tv_usec;
54 return ret;
Armin Rigoa871ef22006-02-08 12:53:56 +000055}
56
57static double
58hpTimerUnit(void)
59{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000060 return 0.000001;
Armin Rigoa871ef22006-02-08 12:53:56 +000061}
62
63#endif /* MS_WINDOWS */
64
65/************************************************************/
66/* Written by Brett Rosen and Ted Czotter */
67
68struct _ProfilerEntry;
69
70/* represents a function called from another function */
71typedef struct _ProfilerSubEntry {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000072 rotating_node_t header;
73 PY_LONG_LONG tt;
74 PY_LONG_LONG it;
75 long callcount;
76 long recursivecallcount;
77 long recursionLevel;
Armin Rigoa871ef22006-02-08 12:53:56 +000078} ProfilerSubEntry;
79
80/* represents a function or user defined block */
81typedef struct _ProfilerEntry {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000082 rotating_node_t header;
83 PyObject *userObj; /* PyCodeObject, or a descriptive str for builtins */
84 PY_LONG_LONG tt; /* total time in this entry */
85 PY_LONG_LONG it; /* inline time in this entry (not in subcalls) */
86 long callcount; /* how many times this was called */
87 long recursivecallcount; /* how many times called recursively */
88 long recursionLevel;
89 rotating_node_t *calls;
Armin Rigoa871ef22006-02-08 12:53:56 +000090} ProfilerEntry;
91
92typedef struct _ProfilerContext {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000093 PY_LONG_LONG t0;
94 PY_LONG_LONG subt;
95 struct _ProfilerContext *previous;
96 ProfilerEntry *ctxEntry;
Armin Rigoa871ef22006-02-08 12:53:56 +000097} ProfilerContext;
98
99typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000100 PyObject_HEAD
101 rotating_node_t *profilerEntries;
102 ProfilerContext *currentProfilerContext;
103 ProfilerContext *freelistProfilerContext;
104 int flags;
105 PyObject *externalTimer;
106 double externalTimerUnit;
Armin Rigoa871ef22006-02-08 12:53:56 +0000107} ProfilerObject;
108
109#define POF_ENABLED 0x001
110#define POF_SUBCALLS 0x002
111#define POF_BUILTINS 0x004
112#define POF_NOMEMORY 0x100
113
Neal Norwitz227b5332006-03-22 09:28:35 +0000114static PyTypeObject PyProfiler_Type;
Armin Rigoa871ef22006-02-08 12:53:56 +0000115
116#define PyProfiler_Check(op) PyObject_TypeCheck(op, &PyProfiler_Type)
Christian Heimes90aa7642007-12-19 02:45:37 +0000117#define PyProfiler_CheckExact(op) (Py_TYPE(op) == &PyProfiler_Type)
Armin Rigoa871ef22006-02-08 12:53:56 +0000118
119/*** External Timers ***/
120
121#define DOUBLE_TIMER_PRECISION 4294967296.0
122static PyObject *empty_tuple;
123
124static PY_LONG_LONG CallExternalTimer(ProfilerObject *pObj)
125{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000126 PY_LONG_LONG result;
127 PyObject *o = PyObject_Call(pObj->externalTimer, empty_tuple, NULL);
128 if (o == NULL) {
129 PyErr_WriteUnraisable(pObj->externalTimer);
130 return 0;
131 }
132 if (pObj->externalTimerUnit > 0.0) {
133 /* interpret the result as an integer that will be scaled
134 in profiler_getstats() */
135 result = PyLong_AsLongLong(o);
136 }
137 else {
138 /* interpret the result as a double measured in seconds.
139 As the profiler works with PY_LONG_LONG internally
140 we convert it to a large integer */
141 double val = PyFloat_AsDouble(o);
142 /* error handling delayed to the code below */
143 result = (PY_LONG_LONG) (val * DOUBLE_TIMER_PRECISION);
144 }
145 Py_DECREF(o);
146 if (PyErr_Occurred()) {
147 PyErr_WriteUnraisable(pObj->externalTimer);
148 return 0;
149 }
150 return result;
Armin Rigoa871ef22006-02-08 12:53:56 +0000151}
152
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000153#define CALL_TIMER(pObj) ((pObj)->externalTimer ? \
154 CallExternalTimer(pObj) : \
155 hpTimer())
Armin Rigoa871ef22006-02-08 12:53:56 +0000156
157/*** ProfilerObject ***/
158
159static PyObject *
160normalizeUserObj(PyObject *obj)
161{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000162 PyCFunctionObject *fn;
163 if (!PyCFunction_Check(obj)) {
164 Py_INCREF(obj);
165 return obj;
166 }
167 /* Replace built-in function objects with a descriptive string
168 because of built-in methods -- keeping a reference to
169 __self__ is probably not a good idea. */
170 fn = (PyCFunctionObject *)obj;
Armin Rigoa871ef22006-02-08 12:53:56 +0000171
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000172 if (fn->m_self == NULL) {
173 /* built-in function: look up the module name */
174 PyObject *mod = fn->m_module;
Victor Stinner7edb5df2011-06-20 14:59:53 +0200175 PyObject *modname = NULL;
176 if (mod != NULL) {
177 if (PyUnicode_Check(mod)) {
178 modname = mod;
179 Py_INCREF(modname);
180 }
181 else if (PyModule_Check(mod)) {
182 modname = PyModule_GetNameObject(mod);
183 if (modname == NULL)
184 PyErr_Clear();
Alexander Belopolskye239d232010-12-08 23:31:48 +0000185 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000186 }
Victor Stinner7edb5df2011-06-20 14:59:53 +0200187 if (modname != NULL) {
Victor Stinnerbd303c12013-11-07 23:07:29 +0100188 if (PyUnicode_CompareWithASCIIString(modname, "builtins") != 0) {
Victor Stinner7edb5df2011-06-20 14:59:53 +0200189 PyObject *result;
190 result = PyUnicode_FromFormat("<%U.%s>", modname,
191 fn->m_ml->ml_name);
192 Py_DECREF(modname);
193 return result;
Alexander Belopolsky532d0912010-12-10 18:14:16 +0000194 }
Victor Stinner7edb5df2011-06-20 14:59:53 +0200195 Py_DECREF(modname);
Alexander Belopolsky532d0912010-12-10 18:14:16 +0000196 }
Victor Stinner7edb5df2011-06-20 14:59:53 +0200197 return PyUnicode_FromFormat("<%s>", fn->m_ml->ml_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000198 }
199 else {
200 /* built-in method: try to return
201 repr(getattr(type(__self__), __name__))
202 */
203 PyObject *self = fn->m_self;
204 PyObject *name = PyUnicode_FromString(fn->m_ml->ml_name);
Antoine Pitrou8477f7a2014-06-27 23:49:29 -0400205 PyObject *modname = fn->m_module;
206
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000207 if (name != NULL) {
208 PyObject *mo = _PyType_Lookup(Py_TYPE(self), name);
209 Py_XINCREF(mo);
210 Py_DECREF(name);
211 if (mo != NULL) {
212 PyObject *res = PyObject_Repr(mo);
213 Py_DECREF(mo);
214 if (res != NULL)
215 return res;
216 }
217 }
Antoine Pitrou8477f7a2014-06-27 23:49:29 -0400218 /* Otherwise, use __module__ */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000219 PyErr_Clear();
Antoine Pitrou8477f7a2014-06-27 23:49:29 -0400220 if (modname != NULL && PyUnicode_Check(modname))
221 return PyUnicode_FromFormat("<built-in method %S.%s>",
222 modname, fn->m_ml->ml_name);
223 else
224 return PyUnicode_FromFormat("<built-in method %s>",
225 fn->m_ml->ml_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000226 }
Armin Rigoa871ef22006-02-08 12:53:56 +0000227}
228
229static ProfilerEntry*
230newProfilerEntry(ProfilerObject *pObj, void *key, PyObject *userObj)
231{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000232 ProfilerEntry *self;
Victor Stinnerb6404912013-07-07 16:21:41 +0200233 self = (ProfilerEntry*) PyMem_Malloc(sizeof(ProfilerEntry));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000234 if (self == NULL) {
235 pObj->flags |= POF_NOMEMORY;
236 return NULL;
237 }
238 userObj = normalizeUserObj(userObj);
239 if (userObj == NULL) {
240 PyErr_Clear();
Victor Stinnerb6404912013-07-07 16:21:41 +0200241 PyMem_Free(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000242 pObj->flags |= POF_NOMEMORY;
243 return NULL;
244 }
245 self->header.key = key;
246 self->userObj = userObj;
247 self->tt = 0;
248 self->it = 0;
249 self->callcount = 0;
250 self->recursivecallcount = 0;
251 self->recursionLevel = 0;
252 self->calls = EMPTY_ROTATING_TREE;
253 RotatingTree_Add(&pObj->profilerEntries, &self->header);
254 return self;
Armin Rigoa871ef22006-02-08 12:53:56 +0000255}
256
257static ProfilerEntry*
258getEntry(ProfilerObject *pObj, void *key)
259{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000260 return (ProfilerEntry*) RotatingTree_Get(&pObj->profilerEntries, key);
Armin Rigoa871ef22006-02-08 12:53:56 +0000261}
262
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000263static ProfilerSubEntry *
Armin Rigoa871ef22006-02-08 12:53:56 +0000264getSubEntry(ProfilerObject *pObj, ProfilerEntry *caller, ProfilerEntry* entry)
265{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000266 return (ProfilerSubEntry*) RotatingTree_Get(&caller->calls,
267 (void *)entry);
Armin Rigoa871ef22006-02-08 12:53:56 +0000268}
269
270static ProfilerSubEntry *
271newSubEntry(ProfilerObject *pObj, ProfilerEntry *caller, ProfilerEntry* entry)
272{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000273 ProfilerSubEntry *self;
Victor Stinnerb6404912013-07-07 16:21:41 +0200274 self = (ProfilerSubEntry*) PyMem_Malloc(sizeof(ProfilerSubEntry));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000275 if (self == NULL) {
276 pObj->flags |= POF_NOMEMORY;
277 return NULL;
278 }
279 self->header.key = (void *)entry;
280 self->tt = 0;
281 self->it = 0;
282 self->callcount = 0;
283 self->recursivecallcount = 0;
284 self->recursionLevel = 0;
285 RotatingTree_Add(&caller->calls, &self->header);
286 return self;
Armin Rigoa871ef22006-02-08 12:53:56 +0000287}
288
289static int freeSubEntry(rotating_node_t *header, void *arg)
290{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000291 ProfilerSubEntry *subentry = (ProfilerSubEntry*) header;
Victor Stinnerb6404912013-07-07 16:21:41 +0200292 PyMem_Free(subentry);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000293 return 0;
Armin Rigoa871ef22006-02-08 12:53:56 +0000294}
295
296static int freeEntry(rotating_node_t *header, void *arg)
297{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000298 ProfilerEntry *entry = (ProfilerEntry*) header;
299 RotatingTree_Enum(entry->calls, freeSubEntry, NULL);
300 Py_DECREF(entry->userObj);
Victor Stinnerb6404912013-07-07 16:21:41 +0200301 PyMem_Free(entry);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000302 return 0;
Armin Rigoa871ef22006-02-08 12:53:56 +0000303}
304
305static void clearEntries(ProfilerObject *pObj)
306{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000307 RotatingTree_Enum(pObj->profilerEntries, freeEntry, NULL);
308 pObj->profilerEntries = EMPTY_ROTATING_TREE;
309 /* release the memory hold by the ProfilerContexts */
310 if (pObj->currentProfilerContext) {
Victor Stinnerb6404912013-07-07 16:21:41 +0200311 PyMem_Free(pObj->currentProfilerContext);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000312 pObj->currentProfilerContext = NULL;
313 }
314 while (pObj->freelistProfilerContext) {
315 ProfilerContext *c = pObj->freelistProfilerContext;
316 pObj->freelistProfilerContext = c->previous;
Victor Stinnerb6404912013-07-07 16:21:41 +0200317 PyMem_Free(c);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000318 }
319 pObj->freelistProfilerContext = NULL;
Armin Rigoa871ef22006-02-08 12:53:56 +0000320}
321
322static void
323initContext(ProfilerObject *pObj, ProfilerContext *self, ProfilerEntry *entry)
324{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000325 self->ctxEntry = entry;
326 self->subt = 0;
327 self->previous = pObj->currentProfilerContext;
328 pObj->currentProfilerContext = self;
329 ++entry->recursionLevel;
330 if ((pObj->flags & POF_SUBCALLS) && self->previous) {
331 /* find or create an entry for me in my caller's entry */
332 ProfilerEntry *caller = self->previous->ctxEntry;
333 ProfilerSubEntry *subentry = getSubEntry(pObj, caller, entry);
334 if (subentry == NULL)
335 subentry = newSubEntry(pObj, caller, entry);
336 if (subentry)
337 ++subentry->recursionLevel;
338 }
339 self->t0 = CALL_TIMER(pObj);
Armin Rigoa871ef22006-02-08 12:53:56 +0000340}
341
342static void
343Stop(ProfilerObject *pObj, ProfilerContext *self, ProfilerEntry *entry)
344{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000345 PY_LONG_LONG tt = CALL_TIMER(pObj) - self->t0;
346 PY_LONG_LONG it = tt - self->subt;
347 if (self->previous)
348 self->previous->subt += tt;
349 pObj->currentProfilerContext = self->previous;
350 if (--entry->recursionLevel == 0)
351 entry->tt += tt;
352 else
353 ++entry->recursivecallcount;
354 entry->it += it;
355 entry->callcount++;
356 if ((pObj->flags & POF_SUBCALLS) && self->previous) {
357 /* find or create an entry for me in my caller's entry */
358 ProfilerEntry *caller = self->previous->ctxEntry;
359 ProfilerSubEntry *subentry = getSubEntry(pObj, caller, entry);
360 if (subentry) {
361 if (--subentry->recursionLevel == 0)
362 subentry->tt += tt;
363 else
364 ++subentry->recursivecallcount;
365 subentry->it += it;
366 ++subentry->callcount;
367 }
368 }
Armin Rigoa871ef22006-02-08 12:53:56 +0000369}
370
371static void
372ptrace_enter_call(PyObject *self, void *key, PyObject *userObj)
373{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000374 /* entering a call to the function identified by 'key'
375 (which can be a PyCodeObject or a PyMethodDef pointer) */
376 ProfilerObject *pObj = (ProfilerObject*)self;
377 ProfilerEntry *profEntry;
378 ProfilerContext *pContext;
Armin Rigoa871ef22006-02-08 12:53:56 +0000379
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000380 /* In the case of entering a generator expression frame via a
381 * throw (gen_send_ex(.., 1)), we may already have an
382 * Exception set here. We must not mess around with this
383 * exception, and some of the code under here assumes that
384 * PyErr_* is its own to mess around with, so we have to
385 * save and restore any current exception. */
386 PyObject *last_type, *last_value, *last_tb;
387 PyErr_Fetch(&last_type, &last_value, &last_tb);
Thomas Wouters89d996e2007-09-08 17:39:28 +0000388
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000389 profEntry = getEntry(pObj, key);
390 if (profEntry == NULL) {
391 profEntry = newProfilerEntry(pObj, key, userObj);
392 if (profEntry == NULL)
393 goto restorePyerr;
394 }
395 /* grab a ProfilerContext out of the free list */
396 pContext = pObj->freelistProfilerContext;
397 if (pContext) {
398 pObj->freelistProfilerContext = pContext->previous;
399 }
400 else {
401 /* free list exhausted, allocate a new one */
402 pContext = (ProfilerContext*)
Victor Stinnerb6404912013-07-07 16:21:41 +0200403 PyMem_Malloc(sizeof(ProfilerContext));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000404 if (pContext == NULL) {
405 pObj->flags |= POF_NOMEMORY;
406 goto restorePyerr;
407 }
408 }
409 initContext(pObj, pContext, profEntry);
Thomas Wouters89d996e2007-09-08 17:39:28 +0000410
411restorePyerr:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000412 PyErr_Restore(last_type, last_value, last_tb);
Armin Rigoa871ef22006-02-08 12:53:56 +0000413}
414
415static void
416ptrace_leave_call(PyObject *self, void *key)
417{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000418 /* leaving a call to the function identified by 'key' */
419 ProfilerObject *pObj = (ProfilerObject*)self;
420 ProfilerEntry *profEntry;
421 ProfilerContext *pContext;
Armin Rigoa871ef22006-02-08 12:53:56 +0000422
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000423 pContext = pObj->currentProfilerContext;
424 if (pContext == NULL)
425 return;
426 profEntry = getEntry(pObj, key);
427 if (profEntry) {
428 Stop(pObj, pContext, profEntry);
429 }
430 else {
431 pObj->currentProfilerContext = pContext->previous;
432 }
433 /* put pContext into the free list */
434 pContext->previous = pObj->freelistProfilerContext;
435 pObj->freelistProfilerContext = pContext;
Armin Rigoa871ef22006-02-08 12:53:56 +0000436}
437
438static int
439profiler_callback(PyObject *self, PyFrameObject *frame, int what,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000440 PyObject *arg)
Armin Rigoa871ef22006-02-08 12:53:56 +0000441{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000442 switch (what) {
Armin Rigoa871ef22006-02-08 12:53:56 +0000443
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000444 /* the 'frame' of a called function is about to start its execution */
445 case PyTrace_CALL:
446 ptrace_enter_call(self, (void *)frame->f_code,
447 (PyObject *)frame->f_code);
448 break;
Armin Rigoa871ef22006-02-08 12:53:56 +0000449
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000450 /* the 'frame' of a called function is about to finish
451 (either normally or with an exception) */
452 case PyTrace_RETURN:
453 ptrace_leave_call(self, (void *)frame->f_code);
454 break;
Armin Rigoa871ef22006-02-08 12:53:56 +0000455
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000456 /* case PyTrace_EXCEPTION:
457 If the exception results in the function exiting, a
458 PyTrace_RETURN event will be generated, so we don't need to
459 handle it. */
Armin Rigoa871ef22006-02-08 12:53:56 +0000460
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000461 /* the Python function 'frame' is issuing a call to the built-in
462 function 'arg' */
463 case PyTrace_C_CALL:
464 if ((((ProfilerObject *)self)->flags & POF_BUILTINS)
465 && PyCFunction_Check(arg)) {
466 ptrace_enter_call(self,
467 ((PyCFunctionObject *)arg)->m_ml,
468 arg);
469 }
470 break;
Armin Rigoa871ef22006-02-08 12:53:56 +0000471
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000472 /* the call to the built-in function 'arg' is returning into its
473 caller 'frame' */
474 case PyTrace_C_RETURN: /* ...normally */
475 case PyTrace_C_EXCEPTION: /* ...with an exception set */
476 if ((((ProfilerObject *)self)->flags & POF_BUILTINS)
477 && PyCFunction_Check(arg)) {
478 ptrace_leave_call(self,
479 ((PyCFunctionObject *)arg)->m_ml);
480 }
481 break;
Armin Rigoa871ef22006-02-08 12:53:56 +0000482
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000483 default:
484 break;
485 }
486 return 0;
Armin Rigoa871ef22006-02-08 12:53:56 +0000487}
488
489static int
490pending_exception(ProfilerObject *pObj)
491{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000492 if (pObj->flags & POF_NOMEMORY) {
493 pObj->flags -= POF_NOMEMORY;
494 PyErr_SetString(PyExc_MemoryError,
495 "memory was exhausted while profiling");
496 return -1;
497 }
498 return 0;
Armin Rigoa871ef22006-02-08 12:53:56 +0000499}
500
501/************************************************************/
502
503static PyStructSequence_Field profiler_entry_fields[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000504 {"code", "code object or built-in function name"},
505 {"callcount", "how many times this was called"},
506 {"reccallcount", "how many times called recursively"},
507 {"totaltime", "total time in this entry"},
508 {"inlinetime", "inline time in this entry (not in subcalls)"},
509 {"calls", "details of the calls"},
510 {0}
Armin Rigoa871ef22006-02-08 12:53:56 +0000511};
512
513static PyStructSequence_Field profiler_subentry_fields[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000514 {"code", "called code object or built-in function name"},
515 {"callcount", "how many times this is called"},
516 {"reccallcount", "how many times this is called recursively"},
517 {"totaltime", "total time spent in this call"},
518 {"inlinetime", "inline time (not in further subcalls)"},
519 {0}
Armin Rigoa871ef22006-02-08 12:53:56 +0000520};
521
522static PyStructSequence_Desc profiler_entry_desc = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000523 "_lsprof.profiler_entry", /* name */
524 NULL, /* doc */
525 profiler_entry_fields,
526 6
Armin Rigoa871ef22006-02-08 12:53:56 +0000527};
528
529static PyStructSequence_Desc profiler_subentry_desc = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000530 "_lsprof.profiler_subentry", /* name */
531 NULL, /* doc */
532 profiler_subentry_fields,
533 5
Armin Rigoa871ef22006-02-08 12:53:56 +0000534};
535
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000536static int initialized;
Armin Rigoa871ef22006-02-08 12:53:56 +0000537static PyTypeObject StatsEntryType;
538static PyTypeObject StatsSubEntryType;
539
540
541typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000542 PyObject *list;
543 PyObject *sublist;
544 double factor;
Armin Rigoa871ef22006-02-08 12:53:56 +0000545} statscollector_t;
546
547static int statsForSubEntry(rotating_node_t *node, void *arg)
548{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000549 ProfilerSubEntry *sentry = (ProfilerSubEntry*) node;
550 statscollector_t *collect = (statscollector_t*) arg;
551 ProfilerEntry *entry = (ProfilerEntry*) sentry->header.key;
552 int err;
553 PyObject *sinfo;
554 sinfo = PyObject_CallFunction((PyObject*) &StatsSubEntryType,
555 "((Olldd))",
556 entry->userObj,
557 sentry->callcount,
558 sentry->recursivecallcount,
559 collect->factor * sentry->tt,
560 collect->factor * sentry->it);
561 if (sinfo == NULL)
562 return -1;
563 err = PyList_Append(collect->sublist, sinfo);
564 Py_DECREF(sinfo);
565 return err;
Armin Rigoa871ef22006-02-08 12:53:56 +0000566}
567
568static int statsForEntry(rotating_node_t *node, void *arg)
569{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000570 ProfilerEntry *entry = (ProfilerEntry*) node;
571 statscollector_t *collect = (statscollector_t*) arg;
572 PyObject *info;
573 int err;
574 if (entry->callcount == 0)
575 return 0; /* skip */
Armin Rigoa871ef22006-02-08 12:53:56 +0000576
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000577 if (entry->calls != EMPTY_ROTATING_TREE) {
578 collect->sublist = PyList_New(0);
579 if (collect->sublist == NULL)
580 return -1;
581 if (RotatingTree_Enum(entry->calls,
582 statsForSubEntry, collect) != 0) {
583 Py_DECREF(collect->sublist);
584 return -1;
585 }
586 }
587 else {
588 Py_INCREF(Py_None);
589 collect->sublist = Py_None;
590 }
Armin Rigoa871ef22006-02-08 12:53:56 +0000591
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000592 info = PyObject_CallFunction((PyObject*) &StatsEntryType,
593 "((OllddO))",
594 entry->userObj,
595 entry->callcount,
596 entry->recursivecallcount,
597 collect->factor * entry->tt,
598 collect->factor * entry->it,
599 collect->sublist);
600 Py_DECREF(collect->sublist);
601 if (info == NULL)
602 return -1;
603 err = PyList_Append(collect->list, info);
604 Py_DECREF(info);
605 return err;
Armin Rigoa871ef22006-02-08 12:53:56 +0000606}
607
608PyDoc_STRVAR(getstats_doc, "\
609getstats() -> list of profiler_entry objects\n\
610\n\
611Return all information collected by the profiler.\n\
612Each profiler_entry is a tuple-like object with the\n\
613following attributes:\n\
614\n\
615 code code object\n\
616 callcount how many times this was called\n\
617 reccallcount how many times called recursively\n\
618 totaltime total time in this entry\n\
619 inlinetime inline time in this entry (not in subcalls)\n\
620 calls details of the calls\n\
621\n\
622The calls attribute is either None or a list of\n\
623profiler_subentry objects:\n\
624\n\
625 code called code object\n\
626 callcount how many times this is called\n\
627 reccallcount how many times this is called recursively\n\
628 totaltime total time spent in this call\n\
629 inlinetime inline time (not in further subcalls)\n\
630");
631
632static PyObject*
633profiler_getstats(ProfilerObject *pObj, PyObject* noarg)
634{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000635 statscollector_t collect;
636 if (pending_exception(pObj))
637 return NULL;
638 if (!pObj->externalTimer)
639 collect.factor = hpTimerUnit();
640 else if (pObj->externalTimerUnit > 0.0)
641 collect.factor = pObj->externalTimerUnit;
642 else
643 collect.factor = 1.0 / DOUBLE_TIMER_PRECISION;
644 collect.list = PyList_New(0);
645 if (collect.list == NULL)
646 return NULL;
647 if (RotatingTree_Enum(pObj->profilerEntries, statsForEntry, &collect)
648 != 0) {
649 Py_DECREF(collect.list);
650 return NULL;
651 }
652 return collect.list;
Armin Rigoa871ef22006-02-08 12:53:56 +0000653}
654
655static int
656setSubcalls(ProfilerObject *pObj, int nvalue)
657{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000658 if (nvalue == 0)
659 pObj->flags &= ~POF_SUBCALLS;
660 else if (nvalue > 0)
661 pObj->flags |= POF_SUBCALLS;
662 return 0;
Armin Rigoa871ef22006-02-08 12:53:56 +0000663}
664
665static int
666setBuiltins(ProfilerObject *pObj, int nvalue)
667{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000668 if (nvalue == 0)
669 pObj->flags &= ~POF_BUILTINS;
670 else if (nvalue > 0) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000671 pObj->flags |= POF_BUILTINS;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000672 }
673 return 0;
Armin Rigoa871ef22006-02-08 12:53:56 +0000674}
675
676PyDoc_STRVAR(enable_doc, "\
677enable(subcalls=True, builtins=True)\n\
678\n\
679Start collecting profiling information.\n\
680If 'subcalls' is True, also records for each function\n\
681statistics separated according to its current caller.\n\
682If 'builtins' is True, records the time spent in\n\
683built-in functions separately from their caller.\n\
684");
685
686static PyObject*
687profiler_enable(ProfilerObject *self, PyObject *args, PyObject *kwds)
688{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000689 int subcalls = -1;
690 int builtins = -1;
691 static char *kwlist[] = {"subcalls", "builtins", 0};
692 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ii:enable",
693 kwlist, &subcalls, &builtins))
694 return NULL;
695 if (setSubcalls(self, subcalls) < 0 || setBuiltins(self, builtins) < 0)
696 return NULL;
697 PyEval_SetProfile(profiler_callback, (PyObject*)self);
698 self->flags |= POF_ENABLED;
699 Py_INCREF(Py_None);
700 return Py_None;
Armin Rigoa871ef22006-02-08 12:53:56 +0000701}
702
703static void
704flush_unmatched(ProfilerObject *pObj)
705{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000706 while (pObj->currentProfilerContext) {
707 ProfilerContext *pContext = pObj->currentProfilerContext;
708 ProfilerEntry *profEntry= pContext->ctxEntry;
709 if (profEntry)
710 Stop(pObj, pContext, profEntry);
711 else
712 pObj->currentProfilerContext = pContext->previous;
713 if (pContext)
Victor Stinnerb6404912013-07-07 16:21:41 +0200714 PyMem_Free(pContext);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000715 }
Armin Rigoa871ef22006-02-08 12:53:56 +0000716
717}
718
719PyDoc_STRVAR(disable_doc, "\
720disable()\n\
721\n\
722Stop collecting profiling information.\n\
723");
724
725static PyObject*
726profiler_disable(ProfilerObject *self, PyObject* noarg)
727{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000728 self->flags &= ~POF_ENABLED;
729 PyEval_SetProfile(NULL, NULL);
730 flush_unmatched(self);
731 if (pending_exception(self))
732 return NULL;
733 Py_INCREF(Py_None);
734 return Py_None;
Armin Rigoa871ef22006-02-08 12:53:56 +0000735}
736
737PyDoc_STRVAR(clear_doc, "\
738clear()\n\
739\n\
740Clear all profiling information collected so far.\n\
741");
742
743static PyObject*
744profiler_clear(ProfilerObject *pObj, PyObject* noarg)
745{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000746 clearEntries(pObj);
747 Py_INCREF(Py_None);
748 return Py_None;
Armin Rigoa871ef22006-02-08 12:53:56 +0000749}
750
751static void
752profiler_dealloc(ProfilerObject *op)
753{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000754 if (op->flags & POF_ENABLED)
755 PyEval_SetProfile(NULL, NULL);
756 flush_unmatched(op);
757 clearEntries(op);
758 Py_XDECREF(op->externalTimer);
759 Py_TYPE(op)->tp_free(op);
Armin Rigoa871ef22006-02-08 12:53:56 +0000760}
761
762static int
763profiler_init(ProfilerObject *pObj, PyObject *args, PyObject *kw)
764{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000765 PyObject *o;
766 PyObject *timer = NULL;
767 double timeunit = 0.0;
768 int subcalls = 1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000769 int builtins = 1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000770 static char *kwlist[] = {"timer", "timeunit",
771 "subcalls", "builtins", 0};
Armin Rigoa871ef22006-02-08 12:53:56 +0000772
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000773 if (!PyArg_ParseTupleAndKeywords(args, kw, "|Odii:Profiler", kwlist,
774 &timer, &timeunit,
775 &subcalls, &builtins))
776 return -1;
Armin Rigoa871ef22006-02-08 12:53:56 +0000777
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000778 if (setSubcalls(pObj, subcalls) < 0 || setBuiltins(pObj, builtins) < 0)
779 return -1;
780 o = pObj->externalTimer;
781 pObj->externalTimer = timer;
782 Py_XINCREF(timer);
783 Py_XDECREF(o);
784 pObj->externalTimerUnit = timeunit;
785 return 0;
Armin Rigoa871ef22006-02-08 12:53:56 +0000786}
787
788static PyMethodDef profiler_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000789 {"getstats", (PyCFunction)profiler_getstats,
790 METH_NOARGS, getstats_doc},
791 {"enable", (PyCFunction)profiler_enable,
792 METH_VARARGS | METH_KEYWORDS, enable_doc},
793 {"disable", (PyCFunction)profiler_disable,
794 METH_NOARGS, disable_doc},
795 {"clear", (PyCFunction)profiler_clear,
796 METH_NOARGS, clear_doc},
797 {NULL, NULL}
Armin Rigoa871ef22006-02-08 12:53:56 +0000798};
799
800PyDoc_STRVAR(profiler_doc, "\
801Profiler(custom_timer=None, time_unit=None, subcalls=True, builtins=True)\n\
802\n\
803 Builds a profiler object using the specified timer function.\n\
804 The default timer is a fast built-in one based on real time.\n\
805 For custom timer functions returning integers, time_unit can\n\
806 be a float specifying a scale (i.e. how long each integer unit\n\
807 is, in seconds).\n\
808");
809
Neal Norwitz227b5332006-03-22 09:28:35 +0000810static PyTypeObject PyProfiler_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000811 PyVarObject_HEAD_INIT(NULL, 0)
812 "_lsprof.Profiler", /* tp_name */
813 sizeof(ProfilerObject), /* tp_basicsize */
814 0, /* tp_itemsize */
815 (destructor)profiler_dealloc, /* tp_dealloc */
816 0, /* tp_print */
817 0, /* tp_getattr */
818 0, /* tp_setattr */
819 0, /* tp_reserved */
820 0, /* tp_repr */
821 0, /* tp_as_number */
822 0, /* tp_as_sequence */
823 0, /* tp_as_mapping */
824 0, /* tp_hash */
825 0, /* tp_call */
826 0, /* tp_str */
827 0, /* tp_getattro */
828 0, /* tp_setattro */
829 0, /* tp_as_buffer */
830 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
831 profiler_doc, /* tp_doc */
832 0, /* tp_traverse */
833 0, /* tp_clear */
834 0, /* tp_richcompare */
835 0, /* tp_weaklistoffset */
836 0, /* tp_iter */
837 0, /* tp_iternext */
838 profiler_methods, /* tp_methods */
839 0, /* tp_members */
840 0, /* tp_getset */
841 0, /* tp_base */
842 0, /* tp_dict */
843 0, /* tp_descr_get */
844 0, /* tp_descr_set */
845 0, /* tp_dictoffset */
846 (initproc)profiler_init, /* tp_init */
847 PyType_GenericAlloc, /* tp_alloc */
848 PyType_GenericNew, /* tp_new */
849 PyObject_Del, /* tp_free */
Armin Rigoa871ef22006-02-08 12:53:56 +0000850};
851
852static PyMethodDef moduleMethods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000853 {NULL, NULL}
Armin Rigoa871ef22006-02-08 12:53:56 +0000854};
855
Martin v. Löwis1a214512008-06-11 05:26:20 +0000856
857static struct PyModuleDef _lsprofmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000858 PyModuleDef_HEAD_INIT,
859 "_lsprof",
860 "Fast profiler",
861 -1,
862 moduleMethods,
863 NULL,
864 NULL,
865 NULL,
866 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +0000867};
868
Armin Rigoa871ef22006-02-08 12:53:56 +0000869PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000870PyInit__lsprof(void)
Armin Rigoa871ef22006-02-08 12:53:56 +0000871{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000872 PyObject *module, *d;
873 module = PyModule_Create(&_lsprofmodule);
874 if (module == NULL)
875 return NULL;
876 d = PyModule_GetDict(module);
877 if (PyType_Ready(&PyProfiler_Type) < 0)
878 return NULL;
879 PyDict_SetItemString(d, "Profiler", (PyObject *)&PyProfiler_Type);
Armin Rigoa871ef22006-02-08 12:53:56 +0000880
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000881 if (!initialized) {
Victor Stinner1c8f0592013-07-22 22:24:54 +0200882 if (PyStructSequence_InitType2(&StatsEntryType,
883 &profiler_entry_desc) < 0)
884 return NULL;
885 if (PyStructSequence_InitType2(&StatsSubEntryType,
886 &profiler_subentry_desc) < 0)
887 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000888 }
889 Py_INCREF((PyObject*) &StatsEntryType);
890 Py_INCREF((PyObject*) &StatsSubEntryType);
891 PyModule_AddObject(module, "profiler_entry",
892 (PyObject*) &StatsEntryType);
893 PyModule_AddObject(module, "profiler_subentry",
894 (PyObject*) &StatsSubEntryType);
895 empty_tuple = PyTuple_New(0);
896 initialized = 1;
897 return module;
Armin Rigoa871ef22006-02-08 12:53:56 +0000898}