Skip to content

Commit cba9a0c

Browse files
authored
bpo-31773: time.perf_counter() uses again double (GH-3964)
time.clock() and time.perf_counter() now use again C double internally. Remove also _PyTime_GetWinPerfCounterWithInfo(): use _PyTime_GetPerfCounterDoubleWithInfo() instead on Windows.
1 parent 0e61e67 commit cba9a0c

File tree

4 files changed

+50
-49
lines changed

4 files changed

+50
-49
lines changed

Include/pytime.h

+12-11
Original file line numberDiff line numberDiff line change
@@ -192,20 +192,21 @@ PyAPI_FUNC(int) _PyTime_localtime(time_t t, struct tm *tm);
192192
Return 0 on success, raise an exception and return -1 on error. */
193193
PyAPI_FUNC(int) _PyTime_gmtime(time_t t, struct tm *tm);
194194

195-
#ifdef MS_WINDOWS
196-
PyAPI_FUNC(int) _PyTime_GetWinPerfCounterWithInfo(
197-
_PyTime_t *t,
198-
_Py_clock_info_t *info);
199-
#endif
195+
/* Get the performance counter: clock with the highest available resolution to
196+
measure a short duration.
197+
198+
The function cannot fail. _PyTime_Init() ensures that the system clock
199+
works. */
200+
PyAPI_FUNC(double) _PyTime_GetPerfCounterDouble(void);
200201

201202
/* Get the performance counter: clock with the highest available resolution to
202-
measure a short duration. */
203-
PyAPI_FUNC(_PyTime_t) _PyTime_GetPerfCounter(void);
203+
measure a short duration.
204204
205-
/* Similar to _PyTime_GetPerfCounter(),
206-
but get also clock info if info is non-NULL. */
207-
PyAPI_FUNC(int) _PyTime_GetPerfCounterWithInfo(
208-
_PyTime_t *t,
205+
Fill info (if set) with information of the function used to get the time.
206+
207+
Return 0 on success, raise an exception and return -1 on error. */
208+
PyAPI_FUNC(int) _PyTime_GetPerfCounterDoubleWithInfo(
209+
double *t,
209210
_Py_clock_info_t *info);
210211

211212
#ifdef __cplusplus

Modules/timemodule.c

+11-17
Original file line numberDiff line numberDiff line change
@@ -88,19 +88,23 @@ floatclock(_Py_clock_info_t *info)
8888
}
8989
#endif /* HAVE_CLOCK */
9090

91+
static PyObject*
92+
perf_counter(_Py_clock_info_t *info)
93+
{
94+
double t;
95+
if (_PyTime_GetPerfCounterDoubleWithInfo(&t, info) < 0) {
96+
return NULL;
97+
}
98+
return PyFloat_FromDouble(t);
99+
}
100+
91101
#if defined(MS_WINDOWS) || defined(HAVE_CLOCK)
92102
#define PYCLOCK
93103
static PyObject*
94104
pyclock(_Py_clock_info_t *info)
95105
{
96106
#ifdef MS_WINDOWS
97-
/* Win32 has better clock replacement; we have our own version, due to Mark
98-
Hammond and Tim Peters */
99-
_PyTime_t t;
100-
if (_PyTime_GetWinPerfCounterWithInfo(&t, info) < 0) {
101-
return NULL;
102-
}
103-
return _PyFloat_FromPyTime(t);
107+
return perf_counter(info);
104108
#else
105109
return floatclock(info);
106110
#endif
@@ -936,16 +940,6 @@ PyDoc_STRVAR(monotonic_doc,
936940
\n\
937941
Monotonic clock, cannot go backward.");
938942

939-
static PyObject*
940-
perf_counter(_Py_clock_info_t *info)
941-
{
942-
_PyTime_t t;
943-
if (_PyTime_GetPerfCounterWithInfo(&t, info) < 0) {
944-
return NULL;
945-
}
946-
return _PyFloat_FromPyTime(t);
947-
}
948-
949943
static PyObject *
950944
time_perf_counter(PyObject *self, PyObject *unused)
951945
{

Python/import.c

+6-6
Original file line numberDiff line numberDiff line change
@@ -1669,10 +1669,10 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals,
16691669
else {
16701670
static int ximporttime = 0;
16711671
static int import_level;
1672-
static _PyTime_t accumulated;
1672+
static double accumulated;
16731673
_Py_IDENTIFIER(importtime);
16741674

1675-
_PyTime_t t1 = 0, accumulated_copy = accumulated;
1675+
double t1 = 0, accumulated_copy = accumulated;
16761676

16771677
Py_XDECREF(mod);
16781678

@@ -1695,7 +1695,7 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals,
16951695

16961696
if (ximporttime) {
16971697
import_level++;
1698-
t1 = _PyTime_GetPerfCounter();
1698+
t1 = _PyTime_GetPerfCounterDouble();
16991699
accumulated = 0;
17001700
}
17011701

@@ -1711,12 +1711,12 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals,
17111711
mod != NULL);
17121712

17131713
if (ximporttime) {
1714-
_PyTime_t cum = _PyTime_GetPerfCounter() - t1;
1714+
double cum = _PyTime_GetPerfCounterDouble() - t1;
17151715

17161716
import_level--;
17171717
fprintf(stderr, "import time: %9ld | %10ld | %*s%s\n",
1718-
(long)_PyTime_AsMicroseconds(cum - accumulated, _PyTime_ROUND_CEILING),
1719-
(long)_PyTime_AsMicroseconds(cum, _PyTime_ROUND_CEILING),
1718+
(long)ceil((cum - accumulated) * 1e6),
1719+
(long)ceil(cum * 1e6),
17201720
import_level*2, "", PyUnicode_AsUTF8(abs_name));
17211721

17221722
accumulated = accumulated_copy + cum;

Python/pytime.c

+21-15
Original file line numberDiff line numberDiff line change
@@ -801,8 +801,8 @@ _PyTime_GetMonotonicClockWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
801801

802802

803803
#ifdef MS_WINDOWS
804-
int
805-
_PyTime_GetWinPerfCounterWithInfo(_PyTime_t *t, _Py_clock_info_t *info)
804+
static int
805+
win_perf_counter(double *tp, _Py_clock_info_t *info)
806806
{
807807
static LONGLONG cpu_frequency = 0;
808808
static LONGLONG ctrStart;
@@ -829,28 +829,33 @@ _PyTime_GetWinPerfCounterWithInfo(_PyTime_t *t, _Py_clock_info_t *info)
829829
}
830830

831831
diff = diff / (double)cpu_frequency;
832-
return _PyTime_FromDouble(t, diff, _PyTime_ROUND_FLOOR, SEC_TO_NS);
832+
*tp = diff;
833+
return 0;
833834
}
834835
#endif
835836

836837

837838
int
838-
_PyTime_GetPerfCounterWithInfo(_PyTime_t *t, _Py_clock_info_t *info)
839+
_PyTime_GetPerfCounterDoubleWithInfo(double *d, _Py_clock_info_t *info)
839840
{
840841
#ifdef MS_WINDOWS
841-
return _PyTime_GetWinPerfCounterWithInfo(t, info);
842+
return win_perf_counter(d, info);
842843
#else
843-
return _PyTime_GetMonotonicClockWithInfo(t, info);
844+
_PyTime_t t;
845+
if (_PyTime_GetMonotonicClockWithInfo(&t, info) < 0) {
846+
return -1;
847+
}
848+
*d = _PyTime_AsSecondsDouble(t);
849+
return 0;
844850
#endif
845851
}
846852

847853

848-
_PyTime_t
849-
_PyTime_GetPerfCounter(void)
854+
double
855+
_PyTime_GetPerfCounterDouble(void)
850856
{
851-
_PyTime_t t;
852-
if (_PyTime_GetPerfCounterWithInfo(&t, NULL) < 0) {
853-
/* should not happen, _PyTime_Init() checked the clock at startup */
857+
double t;
858+
if (_PyTime_GetPerfCounterDoubleWithInfo(&t, NULL)) {
854859
Py_UNREACHABLE();
855860
}
856861
return t;
@@ -860,17 +865,18 @@ _PyTime_GetPerfCounter(void)
860865
int
861866
_PyTime_Init(void)
862867
{
863-
/* check that the 3 most important clocks are working properly
864-
to not have to check for exceptions at runtime. If a clock works once,
865-
it cannot fail in next calls. */
868+
/* check that time.time(), time.monotonic() and time.perf_counter() clocks
869+
are working properly to not have to check for exceptions at runtime. If
870+
a clock works once, it cannot fail in next calls. */
866871
_PyTime_t t;
872+
double d;
867873
if (_PyTime_GetSystemClockWithInfo(&t, NULL) < 0) {
868874
return -1;
869875
}
870876
if (_PyTime_GetMonotonicClockWithInfo(&t, NULL) < 0) {
871877
return -1;
872878
}
873-
if (_PyTime_GetPerfCounterWithInfo(&t, NULL) < 0) {
879+
if (_PyTime_GetPerfCounterDoubleWithInfo(&d, NULL) < 0) {
874880
return -1;
875881
}
876882
return 0;

0 commit comments

Comments
 (0)