[Python-checkins] bpo-31773: time.perf_counter() uses again double (GH-3964)

Victor Stinner webhook-mailer at python.org
Thu Oct 12 11:51:58 EDT 2017


https://github.com/python/cpython/commit/cba9a0c6def70549046f1afa6a80e38fe706520e
commit: cba9a0c6def70549046f1afa6a80e38fe706520e
branch: master
author: Victor Stinner <victor.stinner at gmail.com>
committer: GitHub <noreply at github.com>
date: 2017-10-12T08:51:56-07:00
summary:

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.

files:
M Include/pytime.h
M Modules/timemodule.c
M Python/import.c
M Python/pytime.c

diff --git a/Include/pytime.h b/Include/pytime.h
index 95d482fee3b..fd95045519d 100644
--- a/Include/pytime.h
+++ b/Include/pytime.h
@@ -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. */
 PyAPI_FUNC(int) _PyTime_gmtime(time_t t, struct tm *tm);
 
-#ifdef MS_WINDOWS
-PyAPI_FUNC(int) _PyTime_GetWinPerfCounterWithInfo(
-    _PyTime_t *t,
-    _Py_clock_info_t *info);
-#endif
+/* Get the performance counter: clock with the highest available resolution to
+   measure a short duration.
+
+   The function cannot fail. _PyTime_Init() ensures that the system clock
+   works. */
+PyAPI_FUNC(double) _PyTime_GetPerfCounterDouble(void);
 
 /* Get the performance counter: clock with the highest available resolution to
-   measure a short duration. */
-PyAPI_FUNC(_PyTime_t) _PyTime_GetPerfCounter(void);
+   measure a short duration.
 
-/* Similar to _PyTime_GetPerfCounter(),
-   but get also clock info if info is non-NULL. */
-PyAPI_FUNC(int) _PyTime_GetPerfCounterWithInfo(
-    _PyTime_t *t,
+   Fill info (if set) with information of the function used to get the time.
+
+   Return 0 on success, raise an exception and return -1 on error. */
+PyAPI_FUNC(int) _PyTime_GetPerfCounterDoubleWithInfo(
+    double *t,
     _Py_clock_info_t *info);
 
 #ifdef __cplusplus
diff --git a/Modules/timemodule.c b/Modules/timemodule.c
index 2c0a8d61eda..3cb1b4ec0b6 100644
--- a/Modules/timemodule.c
+++ b/Modules/timemodule.c
@@ -88,19 +88,23 @@ floatclock(_Py_clock_info_t *info)
 }
 #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)
 #define PYCLOCK
 static PyObject*
 pyclock(_Py_clock_info_t *info)
 {
 #ifdef MS_WINDOWS
-    /* Win32 has better clock replacement; we have our own version, due to Mark
-       Hammond and Tim Peters */
-    _PyTime_t t;
-    if (_PyTime_GetWinPerfCounterWithInfo(&t, info) < 0) {
-        return NULL;
-    }
-    return _PyFloat_FromPyTime(t);
+    return perf_counter(info);
 #else
     return floatclock(info);
 #endif
@@ -936,16 +940,6 @@ PyDoc_STRVAR(monotonic_doc,
 \n\
 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 *
 time_perf_counter(PyObject *self, PyObject *unused)
 {
diff --git a/Python/import.c b/Python/import.c
index d396b4de793..76aa912dc86 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -1669,10 +1669,10 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals,
     else {
         static int ximporttime = 0;
         static int import_level;
-        static _PyTime_t accumulated;
+        static double accumulated;
         _Py_IDENTIFIER(importtime);
 
-        _PyTime_t t1 = 0, accumulated_copy = accumulated;
+        double t1 = 0, accumulated_copy = accumulated;
 
         Py_XDECREF(mod);
 
@@ -1695,7 +1695,7 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals,
 
         if (ximporttime) {
             import_level++;
-            t1 = _PyTime_GetPerfCounter();
+            t1 = _PyTime_GetPerfCounterDouble();
             accumulated = 0;
         }
 
@@ -1711,12 +1711,12 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals,
                                            mod != NULL);
 
         if (ximporttime) {
-            _PyTime_t cum = _PyTime_GetPerfCounter() - t1;
+            double cum = _PyTime_GetPerfCounterDouble() - t1;
 
             import_level--;
             fprintf(stderr, "import time: %9ld | %10ld | %*s%s\n",
-                    (long)_PyTime_AsMicroseconds(cum - accumulated, _PyTime_ROUND_CEILING),
-                    (long)_PyTime_AsMicroseconds(cum, _PyTime_ROUND_CEILING),
+                    (long)ceil((cum - accumulated) * 1e6),
+                    (long)ceil(cum * 1e6),
                     import_level*2, "", PyUnicode_AsUTF8(abs_name));
 
             accumulated = accumulated_copy + cum;
diff --git a/Python/pytime.c b/Python/pytime.c
index dbf1dda4a0e..7fd2a90f3bd 100644
--- a/Python/pytime.c
+++ b/Python/pytime.c
@@ -801,8 +801,8 @@ _PyTime_GetMonotonicClockWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
 
 
 #ifdef MS_WINDOWS
-int
-_PyTime_GetWinPerfCounterWithInfo(_PyTime_t *t, _Py_clock_info_t *info)
+static int
+win_perf_counter(double *tp, _Py_clock_info_t *info)
 {
     static LONGLONG cpu_frequency = 0;
     static LONGLONG ctrStart;
@@ -829,28 +829,33 @@ _PyTime_GetWinPerfCounterWithInfo(_PyTime_t *t, _Py_clock_info_t *info)
     }
 
     diff = diff / (double)cpu_frequency;
-    return _PyTime_FromDouble(t, diff, _PyTime_ROUND_FLOOR, SEC_TO_NS);
+    *tp = diff;
+    return 0;
 }
 #endif
 
 
 int
-_PyTime_GetPerfCounterWithInfo(_PyTime_t *t, _Py_clock_info_t *info)
+_PyTime_GetPerfCounterDoubleWithInfo(double *d, _Py_clock_info_t *info)
 {
 #ifdef MS_WINDOWS
-    return _PyTime_GetWinPerfCounterWithInfo(t, info);
+    return win_perf_counter(d, info);
 #else
-    return _PyTime_GetMonotonicClockWithInfo(t, info);
+    _PyTime_t t;
+    if (_PyTime_GetMonotonicClockWithInfo(&t, info) < 0) {
+        return -1;
+    }
+    *d = _PyTime_AsSecondsDouble(t);
+    return 0;
 #endif
 }
 
 
-_PyTime_t
-_PyTime_GetPerfCounter(void)
+double
+_PyTime_GetPerfCounterDouble(void)
 {
-    _PyTime_t t;
-    if (_PyTime_GetPerfCounterWithInfo(&t, NULL) < 0) {
-        /* should not happen, _PyTime_Init() checked the clock at startup */
+    double t;
+    if (_PyTime_GetPerfCounterDoubleWithInfo(&t, NULL)) {
         Py_UNREACHABLE();
     }
     return t;
@@ -860,17 +865,18 @@ _PyTime_GetPerfCounter(void)
 int
 _PyTime_Init(void)
 {
-    /* check that the 3 most important clocks are working properly
-       to not have to check for exceptions at runtime. If a clock works once,
-       it cannot fail in next calls. */
+    /* check that time.time(), time.monotonic() and time.perf_counter() clocks
+       are working properly to not have to check for exceptions at runtime. If
+       a clock works once, it cannot fail in next calls. */
     _PyTime_t t;
+    double d;
     if (_PyTime_GetSystemClockWithInfo(&t, NULL) < 0) {
         return -1;
     }
     if (_PyTime_GetMonotonicClockWithInfo(&t, NULL) < 0) {
         return -1;
     }
-    if (_PyTime_GetPerfCounterWithInfo(&t, NULL) < 0) {
+    if (_PyTime_GetPerfCounterDoubleWithInfo(&d, NULL) < 0) {
         return -1;
     }
     return 0;



More information about the Python-checkins mailing list