22#include "frameobject.h"
33#include "rotatingtree.h"
44
5- /*** Selection of a high-precision timer ***/
6-
7- #ifdef MS_WINDOWS
8-
9- #include <windows.h>
10-
11- static long long
12- hpTimer (void )
13- {
14- LARGE_INTEGER li ;
15- QueryPerformanceCounter (& li );
16- return li .QuadPart ;
17- }
18-
19- static double
20- hpTimerUnit (void )
21- {
22- LARGE_INTEGER li ;
23- if (QueryPerformanceFrequency (& li ))
24- return 1.0 / li .QuadPart ;
25- else
26- return 0.000001 ; /* unlikely */
27- }
28-
29- #else /* !MS_WINDOWS */
30-
31- #ifndef HAVE_GETTIMEOFDAY
32- #error "This module requires gettimeofday() on non-Windows platforms!"
33- #endif
34-
35- #include <sys/resource.h>
36- #include <sys/times.h>
37-
38- static long long
39- hpTimer (void )
40- {
41- struct timeval tv ;
42- long long ret ;
43- #ifdef GETTIMEOFDAY_NO_TZ
44- gettimeofday (& tv );
45- #else
46- gettimeofday (& tv , (struct timezone * )NULL );
47- #endif
48- ret = tv .tv_sec ;
49- ret = ret * 1000000 + tv .tv_usec ;
50- return ret ;
51- }
52-
53- static double
54- hpTimerUnit (void )
55- {
56- return 0.000001 ;
57- }
58-
59- #endif /* MS_WINDOWS */
60-
615/************************************************************/
626/* Written by Brett Rosen and Ted Czotter */
637
@@ -66,8 +10,8 @@ struct _ProfilerEntry;
6610/* represents a function called from another function */
6711typedef struct _ProfilerSubEntry {
6812 rotating_node_t header ;
69- long long tt ;
70- long long it ;
13+ _PyTime_t tt ;
14+ _PyTime_t it ;
7115 long callcount ;
7216 long recursivecallcount ;
7317 long recursionLevel ;
@@ -77,17 +21,17 @@ typedef struct _ProfilerSubEntry {
7721typedef struct _ProfilerEntry {
7822 rotating_node_t header ;
7923 PyObject * userObj ; /* PyCodeObject, or a descriptive str for builtins */
80- long long tt ; /* total time in this entry */
81- long long it ; /* inline time in this entry (not in subcalls) */
24+ _PyTime_t tt ; /* total time in this entry */
25+ _PyTime_t it ; /* inline time in this entry (not in subcalls) */
8226 long callcount ; /* how many times this was called */
8327 long recursivecallcount ; /* how many times called recursively */
8428 long recursionLevel ;
8529 rotating_node_t * calls ;
8630} ProfilerEntry ;
8731
8832typedef struct _ProfilerContext {
89- long long t0 ;
90- long long subt ;
33+ _PyTime_t t0 ;
34+ _PyTime_t subt ;
9135 struct _ProfilerContext * previous ;
9236 ProfilerEntry * ctxEntry ;
9337} ProfilerContext ;
@@ -114,41 +58,46 @@ static PyTypeObject PyProfiler_Type;
11458
11559/*** External Timers ***/
11660
117- #define DOUBLE_TIMER_PRECISION 4294967296.0
118- static PyObject * empty_tuple ;
119-
120- static long long CallExternalTimer (ProfilerObject * pObj )
61+ static _PyTime_t CallExternalTimer (ProfilerObject * pObj )
12162{
122- long long result ;
123- PyObject * o = PyObject_Call (pObj -> externalTimer , empty_tuple , NULL );
63+ PyObject * o = _PyObject_CallNoArg (pObj -> externalTimer );
12464 if (o == NULL ) {
12565 PyErr_WriteUnraisable (pObj -> externalTimer );
12666 return 0 ;
12767 }
68+
69+ _PyTime_t result ;
70+ int err ;
12871 if (pObj -> externalTimerUnit > 0.0 ) {
12972 /* interpret the result as an integer that will be scaled
13073 in profiler_getstats() */
131- result = PyLong_AsLongLong ( o );
74+ err = _PyTime_FromNanosecondsObject ( & result , o );
13275 }
13376 else {
13477 /* interpret the result as a double measured in seconds.
135- As the profiler works with long long internally
78+ As the profiler works with _PyTime_t internally
13679 we convert it to a large integer */
137- double val = PyFloat_AsDouble (o );
138- /* error handling delayed to the code below */
139- result = (long long ) (val * DOUBLE_TIMER_PRECISION );
80+ err = _PyTime_FromSecondsObject (& result , o , _PyTime_ROUND_FLOOR );
14081 }
14182 Py_DECREF (o );
142- if (PyErr_Occurred () ) {
83+ if (err < 0 ) {
14384 PyErr_WriteUnraisable (pObj -> externalTimer );
14485 return 0 ;
14586 }
14687 return result ;
14788}
14889
149- #define CALL_TIMER (pObj ) ((pObj)->externalTimer ? \
150- CallExternalTimer(pObj) : \
151- hpTimer())
90+ static inline _PyTime_t
91+ call_timer (ProfilerObject * pObj )
92+ {
93+ if (pObj -> externalTimer != NULL ) {
94+ return CallExternalTimer (pObj );
95+ }
96+ else {
97+ return _PyTime_GetPerfCounter ();
98+ }
99+ }
100+
152101
153102/*** ProfilerObject ***/
154103
@@ -332,14 +281,14 @@ initContext(ProfilerObject *pObj, ProfilerContext *self, ProfilerEntry *entry)
332281 if (subentry )
333282 ++ subentry -> recursionLevel ;
334283 }
335- self -> t0 = CALL_TIMER (pObj );
284+ self -> t0 = call_timer (pObj );
336285}
337286
338287static void
339288Stop (ProfilerObject * pObj , ProfilerContext * self , ProfilerEntry * entry )
340289{
341- long long tt = CALL_TIMER (pObj ) - self -> t0 ;
342- long long it = tt - self -> subt ;
290+ _PyTime_t tt = call_timer (pObj ) - self -> t0 ;
291+ _PyTime_t it = tt - self -> subt ;
343292 if (self -> previous )
344293 self -> previous -> subt += tt ;
345294 pObj -> currentProfilerContext = self -> previous ;
@@ -631,12 +580,14 @@ profiler_getstats(ProfilerObject *pObj, PyObject* noarg)
631580 statscollector_t collect ;
632581 if (pending_exception (pObj ))
633582 return NULL ;
634- if (!pObj -> externalTimer )
635- collect .factor = hpTimerUnit ();
636- else if (pObj -> externalTimerUnit > 0.0 )
583+ if (!pObj -> externalTimer || pObj -> externalTimerUnit == 0.0 ) {
584+ _PyTime_t onesec = _PyTime_FromSeconds (1 );
585+ collect .factor = (double )1 / onesec ;
586+ }
587+ else {
637588 collect .factor = pObj -> externalTimerUnit ;
638- else
639- collect . factor = 1.0 / DOUBLE_TIMER_PRECISION ;
589+ }
590+
640591 collect .list = PyList_New (0 );
641592 if (collect .list == NULL )
642593 return NULL ;
@@ -882,7 +833,6 @@ PyInit__lsprof(void)
882833 (PyObject * ) & StatsEntryType );
883834 PyModule_AddObject (module , "profiler_subentry" ,
884835 (PyObject * ) & StatsSubEntryType );
885- empty_tuple = PyTuple_New (0 );
886836 initialized = 1 ;
887837 return module ;
888838}
0 commit comments