2
2
#include "frameobject.h"
3
3
#include "rotatingtree.h"
4
4
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
-
61
5
/************************************************************/
62
6
/* Written by Brett Rosen and Ted Czotter */
63
7
@@ -66,8 +10,8 @@ struct _ProfilerEntry;
66
10
/* represents a function called from another function */
67
11
typedef struct _ProfilerSubEntry {
68
12
rotating_node_t header ;
69
- long long tt ;
70
- long long it ;
13
+ _PyTime_t tt ;
14
+ _PyTime_t it ;
71
15
long callcount ;
72
16
long recursivecallcount ;
73
17
long recursionLevel ;
@@ -77,17 +21,17 @@ typedef struct _ProfilerSubEntry {
77
21
typedef struct _ProfilerEntry {
78
22
rotating_node_t header ;
79
23
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) */
82
26
long callcount ; /* how many times this was called */
83
27
long recursivecallcount ; /* how many times called recursively */
84
28
long recursionLevel ;
85
29
rotating_node_t * calls ;
86
30
} ProfilerEntry ;
87
31
88
32
typedef struct _ProfilerContext {
89
- long long t0 ;
90
- long long subt ;
33
+ _PyTime_t t0 ;
34
+ _PyTime_t subt ;
91
35
struct _ProfilerContext * previous ;
92
36
ProfilerEntry * ctxEntry ;
93
37
} ProfilerContext ;
@@ -114,41 +58,46 @@ static PyTypeObject PyProfiler_Type;
114
58
115
59
/*** External Timers ***/
116
60
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 )
121
62
{
122
- long long result ;
123
- PyObject * o = PyObject_Call (pObj -> externalTimer , empty_tuple , NULL );
63
+ PyObject * o = _PyObject_CallNoArg (pObj -> externalTimer );
124
64
if (o == NULL ) {
125
65
PyErr_WriteUnraisable (pObj -> externalTimer );
126
66
return 0 ;
127
67
}
68
+
69
+ _PyTime_t result ;
70
+ int err ;
128
71
if (pObj -> externalTimerUnit > 0.0 ) {
129
72
/* interpret the result as an integer that will be scaled
130
73
in profiler_getstats() */
131
- result = PyLong_AsLongLong ( o );
74
+ err = _PyTime_FromNanosecondsObject ( & result , o );
132
75
}
133
76
else {
134
77
/* 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
136
79
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 );
140
81
}
141
82
Py_DECREF (o );
142
- if (PyErr_Occurred () ) {
83
+ if (err < 0 ) {
143
84
PyErr_WriteUnraisable (pObj -> externalTimer );
144
85
return 0 ;
145
86
}
146
87
return result ;
147
88
}
148
89
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
+
152
101
153
102
/*** ProfilerObject ***/
154
103
@@ -332,14 +281,14 @@ initContext(ProfilerObject *pObj, ProfilerContext *self, ProfilerEntry *entry)
332
281
if (subentry )
333
282
++ subentry -> recursionLevel ;
334
283
}
335
- self -> t0 = CALL_TIMER (pObj );
284
+ self -> t0 = call_timer (pObj );
336
285
}
337
286
338
287
static void
339
288
Stop (ProfilerObject * pObj , ProfilerContext * self , ProfilerEntry * entry )
340
289
{
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 ;
343
292
if (self -> previous )
344
293
self -> previous -> subt += tt ;
345
294
pObj -> currentProfilerContext = self -> previous ;
@@ -631,12 +580,14 @@ profiler_getstats(ProfilerObject *pObj, PyObject* noarg)
631
580
statscollector_t collect ;
632
581
if (pending_exception (pObj ))
633
582
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 {
637
588
collect .factor = pObj -> externalTimerUnit ;
638
- else
639
- collect . factor = 1.0 / DOUBLE_TIMER_PRECISION ;
589
+ }
590
+
640
591
collect .list = PyList_New (0 );
641
592
if (collect .list == NULL )
642
593
return NULL ;
@@ -882,7 +833,6 @@ PyInit__lsprof(void)
882
833
(PyObject * ) & StatsEntryType );
883
834
PyModule_AddObject (module , "profiler_subentry" ,
884
835
(PyObject * ) & StatsSubEntryType );
885
- empty_tuple = PyTuple_New (0 );
886
836
initialized = 1 ;
887
837
return module ;
888
838
}
0 commit comments