diff --git a/Doc/library/time.rst b/Doc/library/time.rst --- a/Doc/library/time.rst +++ b/Doc/library/time.rst @@ -183,6 +183,18 @@ The module defines the following functio .. versionadded:: 3.3 +.. function:: wallclock() + + .. index:: + single: Wallclock + single: benchmarking + + Return the current time in fractions of a second to the system's best ability. + Use this when the most accurate representation of wall-clock is required, i.e. + when "processor time" is inappropriate. The reference point of the returned + value is undefined so only the difference of consecutive calls is valid. + + .. versionadded: 3.3 .. function:: ctime([secs]) diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py --- a/Lib/test/test_time.py +++ b/Lib/test/test_time.py @@ -325,6 +325,13 @@ class TimeTestCase(unittest.TestCase): self.assertEqual(time.strftime('%Z', tt), tzname) + def test_wallclock(self): + t0 = time.wallclock() + time.sleep(0.1) + t1 = time.wallclock() + t = t1 - t0 + self.assertAlmostEqual(t, 0.1, places=2) + class TestLocale(unittest.TestCase): def setUp(self): self.oldloc = locale.setlocale(locale.LC_ALL) diff --git a/Modules/timemodule.c b/Modules/timemodule.c --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -733,6 +733,44 @@ the local timezone used by methods such should not be relied on."); #endif /* HAVE_WORKING_TZSET */ +static PyObject * +time_wallclock(PyObject *self, PyObject *unused) +{ +#if defined(MS_WINDOWS) && !defined(__BORLANDC__) + return time_clock(self, NULL); +#elif defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) + static int clk_index = 0; + clockid_t clk_ids[] = { +#ifdef CLOCK_MONOTONIC_RAW + CLOCK_MONOTONIC_RAW, +#endif + CLOCK_MONOTONIC}; + int ret; + struct timespec tp; + + while (0 <= clk_index) { + clockid_t clk_id = clk_ids[clk_index]; + ret = clock_gettime(clk_id, &tp); + if (ret == 0) + return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9); + + clk_index++; + if (Py_ARRAY_LENGTH(clk_ids) <= clk_index) + clk_index = -1; + } + return time_time(self, NULL); +#else + return time_time(self, NULL); +#endif +} + +PyDoc_STRVAR(wallclock_doc, +"wallclock() -> floating point number\n\ +\n\ +Return the real time to the best of the system's ability. The absolute\n\ +value is not specified and only relative values between subsequent calls\n\ +are defined to have meaning."); + static void PyInit_timezone(PyObject *m) { /* This code moved from PyInit_time wholesale to allow calling it from @@ -868,6 +906,7 @@ static PyMethodDef time_methods[] = { #ifdef HAVE_WORKING_TZSET {"tzset", time_tzset, METH_NOARGS, tzset_doc}, #endif + {"wallclock", time_wallclock, METH_NOARGS, wallclock_doc}, {NULL, NULL} /* sentinel */ };