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.
This commit is contained in:
Victor Stinner 2017-10-12 08:51:56 -07:00 committed by GitHub
parent 0e61e67a57
commit cba9a0c6de
4 changed files with 50 additions and 49 deletions

View File

@ -192,20 +192,21 @@ PyAPI_FUNC(int) _PyTime_localtime(time_t t, struct tm *tm);
Return 0 on success, raise an exception and return -1 on error. */ Return 0 on success, raise an exception and return -1 on error. */
PyAPI_FUNC(int) _PyTime_gmtime(time_t t, struct tm *tm); PyAPI_FUNC(int) _PyTime_gmtime(time_t t, struct tm *tm);
#ifdef MS_WINDOWS /* Get the performance counter: clock with the highest available resolution to
PyAPI_FUNC(int) _PyTime_GetWinPerfCounterWithInfo( measure a short duration.
_PyTime_t *t,
_Py_clock_info_t *info); The function cannot fail. _PyTime_Init() ensures that the system clock
#endif works. */
PyAPI_FUNC(double) _PyTime_GetPerfCounterDouble(void);
/* Get the performance counter: clock with the highest available resolution to /* Get the performance counter: clock with the highest available resolution to
measure a short duration. */ measure a short duration.
PyAPI_FUNC(_PyTime_t) _PyTime_GetPerfCounter(void);
/* Similar to _PyTime_GetPerfCounter(), Fill info (if set) with information of the function used to get the time.
but get also clock info if info is non-NULL. */
PyAPI_FUNC(int) _PyTime_GetPerfCounterWithInfo( Return 0 on success, raise an exception and return -1 on error. */
_PyTime_t *t, PyAPI_FUNC(int) _PyTime_GetPerfCounterDoubleWithInfo(
double *t,
_Py_clock_info_t *info); _Py_clock_info_t *info);
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -88,19 +88,23 @@ floatclock(_Py_clock_info_t *info)
} }
#endif /* HAVE_CLOCK */ #endif /* HAVE_CLOCK */
static PyObject*
perf_counter(_Py_clock_info_t *info)
{
double t;
if (_PyTime_GetPerfCounterDoubleWithInfo(&t, info) < 0) {
return NULL;
}
return PyFloat_FromDouble(t);
}
#if defined(MS_WINDOWS) || defined(HAVE_CLOCK) #if defined(MS_WINDOWS) || defined(HAVE_CLOCK)
#define PYCLOCK #define PYCLOCK
static PyObject* static PyObject*
pyclock(_Py_clock_info_t *info) pyclock(_Py_clock_info_t *info)
{ {
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
/* Win32 has better clock replacement; we have our own version, due to Mark return perf_counter(info);
Hammond and Tim Peters */
_PyTime_t t;
if (_PyTime_GetWinPerfCounterWithInfo(&t, info) < 0) {
return NULL;
}
return _PyFloat_FromPyTime(t);
#else #else
return floatclock(info); return floatclock(info);
#endif #endif
@ -936,16 +940,6 @@ PyDoc_STRVAR(monotonic_doc,
\n\ \n\
Monotonic clock, cannot go backward."); Monotonic clock, cannot go backward.");
static PyObject*
perf_counter(_Py_clock_info_t *info)
{
_PyTime_t t;
if (_PyTime_GetPerfCounterWithInfo(&t, info) < 0) {
return NULL;
}
return _PyFloat_FromPyTime(t);
}
static PyObject * static PyObject *
time_perf_counter(PyObject *self, PyObject *unused) time_perf_counter(PyObject *self, PyObject *unused)
{ {

View File

@ -1669,10 +1669,10 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals,
else { else {
static int ximporttime = 0; static int ximporttime = 0;
static int import_level; static int import_level;
static _PyTime_t accumulated; static double accumulated;
_Py_IDENTIFIER(importtime); _Py_IDENTIFIER(importtime);
_PyTime_t t1 = 0, accumulated_copy = accumulated; double t1 = 0, accumulated_copy = accumulated;
Py_XDECREF(mod); Py_XDECREF(mod);
@ -1695,7 +1695,7 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals,
if (ximporttime) { if (ximporttime) {
import_level++; import_level++;
t1 = _PyTime_GetPerfCounter(); t1 = _PyTime_GetPerfCounterDouble();
accumulated = 0; accumulated = 0;
} }
@ -1711,12 +1711,12 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals,
mod != NULL); mod != NULL);
if (ximporttime) { if (ximporttime) {
_PyTime_t cum = _PyTime_GetPerfCounter() - t1; double cum = _PyTime_GetPerfCounterDouble() - t1;
import_level--; import_level--;
fprintf(stderr, "import time: %9ld | %10ld | %*s%s\n", fprintf(stderr, "import time: %9ld | %10ld | %*s%s\n",
(long)_PyTime_AsMicroseconds(cum - accumulated, _PyTime_ROUND_CEILING), (long)ceil((cum - accumulated) * 1e6),
(long)_PyTime_AsMicroseconds(cum, _PyTime_ROUND_CEILING), (long)ceil(cum * 1e6),
import_level*2, "", PyUnicode_AsUTF8(abs_name)); import_level*2, "", PyUnicode_AsUTF8(abs_name));
accumulated = accumulated_copy + cum; accumulated = accumulated_copy + cum;

View File

@ -801,8 +801,8 @@ _PyTime_GetMonotonicClockWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
int static int
_PyTime_GetWinPerfCounterWithInfo(_PyTime_t *t, _Py_clock_info_t *info) win_perf_counter(double *tp, _Py_clock_info_t *info)
{ {
static LONGLONG cpu_frequency = 0; static LONGLONG cpu_frequency = 0;
static LONGLONG ctrStart; static LONGLONG ctrStart;
@ -829,28 +829,33 @@ _PyTime_GetWinPerfCounterWithInfo(_PyTime_t *t, _Py_clock_info_t *info)
} }
diff = diff / (double)cpu_frequency; diff = diff / (double)cpu_frequency;
return _PyTime_FromDouble(t, diff, _PyTime_ROUND_FLOOR, SEC_TO_NS); *tp = diff;
return 0;
} }
#endif #endif
int int
_PyTime_GetPerfCounterWithInfo(_PyTime_t *t, _Py_clock_info_t *info) _PyTime_GetPerfCounterDoubleWithInfo(double *d, _Py_clock_info_t *info)
{ {
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
return _PyTime_GetWinPerfCounterWithInfo(t, info); return win_perf_counter(d, info);
#else #else
return _PyTime_GetMonotonicClockWithInfo(t, info); _PyTime_t t;
if (_PyTime_GetMonotonicClockWithInfo(&t, info) < 0) {
return -1;
}
*d = _PyTime_AsSecondsDouble(t);
return 0;
#endif #endif
} }
_PyTime_t double
_PyTime_GetPerfCounter(void) _PyTime_GetPerfCounterDouble(void)
{ {
_PyTime_t t; double t;
if (_PyTime_GetPerfCounterWithInfo(&t, NULL) < 0) { if (_PyTime_GetPerfCounterDoubleWithInfo(&t, NULL)) {
/* should not happen, _PyTime_Init() checked the clock at startup */
Py_UNREACHABLE(); Py_UNREACHABLE();
} }
return t; return t;
@ -860,17 +865,18 @@ _PyTime_GetPerfCounter(void)
int int
_PyTime_Init(void) _PyTime_Init(void)
{ {
/* check that the 3 most important clocks are working properly /* check that time.time(), time.monotonic() and time.perf_counter() clocks
to not have to check for exceptions at runtime. If a clock works once, are working properly to not have to check for exceptions at runtime. If
it cannot fail in next calls. */ a clock works once, it cannot fail in next calls. */
_PyTime_t t; _PyTime_t t;
double d;
if (_PyTime_GetSystemClockWithInfo(&t, NULL) < 0) { if (_PyTime_GetSystemClockWithInfo(&t, NULL) < 0) {
return -1; return -1;
} }
if (_PyTime_GetMonotonicClockWithInfo(&t, NULL) < 0) { if (_PyTime_GetMonotonicClockWithInfo(&t, NULL) < 0) {
return -1; return -1;
} }
if (_PyTime_GetPerfCounterWithInfo(&t, NULL) < 0) { if (_PyTime_GetPerfCounterDoubleWithInfo(&d, NULL) < 0) {
return -1; return -1;
} }
return 0; return 0;