Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 49 additions & 6 deletions Doc/library/time.rst
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ Functions
.. versionadded:: 3.3


.. function:: clock_gettime(clk_id)
.. function:: clock_gettime(clk_id) -> float

Return the time of the specified clock *clk_id*. Refer to
:ref:`time-clock-id-constants` for a list of accepted values for *clk_id*.
Expand All @@ -195,7 +195,16 @@ Functions
.. versionadded:: 3.3


.. function:: clock_settime(clk_id, time)
.. function:: clock_gettime_ns(clk_id) -> int

Similar to :func:`clock_gettime` but return time as nanoseconds.

Availability: Unix.

.. versionadded:: 3.7


.. function:: clock_settime(clk_id, time: float)

Set the time of the specified clock *clk_id*. Currently,
:data:`CLOCK_REALTIME` is the only accepted value for *clk_id*.
Expand All @@ -205,6 +214,15 @@ Functions
.. versionadded:: 3.3


.. function:: clock_settime_ns(clk_id, time: int)

Similar to :func:`clock_settime` but set time with nanoseconds.

Availability: Unix.

.. versionadded:: 3.7


.. function:: ctime([secs])

Convert a time expressed in seconds since the epoch to a string representing
Expand Down Expand Up @@ -267,7 +285,7 @@ Functions
The earliest date for which it can generate a time is platform-dependent.


.. function:: monotonic()
.. function:: monotonic() -> float

Return the value (in fractional seconds) of a monotonic clock, i.e. a clock
that cannot go backwards. The clock is not affected by system clock updates.
Expand All @@ -287,7 +305,13 @@ Functions
The function is now always available.


.. function:: perf_counter()
.. function:: monotonic_ns() -> int

Similar to :func:`monotonic`, but return time as nanoseconds.

.. versionadded:: 3.7

.. function:: perf_counter() -> float

.. index::
single: benchmarking
Expand All @@ -300,8 +324,14 @@ Functions

.. versionadded:: 3.3

.. function:: perf_counter_ns() -> int

Similar to :func:`perf_counter`, but return time as nanoseconds.

.. versionadded:: 3.7

.. function:: process_time()

.. function:: process_time() -> float

.. index::
single: CPU time
Expand All @@ -316,6 +346,12 @@ Functions

.. versionadded:: 3.3

.. function:: process_time_ns() -> int

Similar to :func:`process_time` but return time as nanoseconds.

.. versionadded:: 3.7

.. function:: sleep(secs)

Suspend execution of the calling thread for the given number of seconds.
Expand Down Expand Up @@ -541,7 +577,7 @@ Functions
:class:`struct_time`, or having elements of the wrong type, a
:exc:`TypeError` is raised.

.. function:: time()
.. function:: time() -> float

Return the time in seconds since the epoch_ as a floating point
number. The specific date of the epoch and the handling of
Expand All @@ -567,6 +603,13 @@ Functions
of the calendar date may be accessed as attributes.


.. function:: time_ns() -> int

Similar to :func:`time` but returns time as an integer number of nanoseconds
since the epoch_.

.. versionadded:: 3.7

.. function:: tzset()

Reset the time conversion rules used by the library routines. The environment
Expand Down
35 changes: 35 additions & 0 deletions Doc/whatsnew/3.7.rst
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,32 @@ effort will be made to add such support.
PEP written by Erik M. Bray; implementation by Masayuki Yamamoto.


PEP 564: Add new time functions with nanosecond resolution
----------------------------------------------------------

Add six new "nanosecond" variants of existing functions to the :mod:`time`
module:

* :func:`time.clock_gettime_ns`
* :func:`time.clock_settime_ns`
* :func:`time.monotonic_ns`
* :func:`time.perf_counter_ns`
* :func:`time.process_time_ns`
* :func:`time.time_ns`

While similar to the existing functions without the ``_ns`` suffix, they
provide nanosecond resolution: they return a number of nanoseconds as a Python
``int``.

The ``time.time_ns()`` resolution is 3 times better than the ``time.time()``
resolution on Linux and Windows.

.. seealso::

:pep:`564` -- Add new time functions with nanosecond resolution
PEP written and implemented by Victor Stinner


Other Language Changes
======================

Expand Down Expand Up @@ -313,6 +339,15 @@ separately. (Contributed by Barry Warsaw in :issue:`1198569`.)
time
----

The :pep:`564` added six new functions with nanosecond resolution:

* :func:`time.clock_gettime_ns`
* :func:`time.clock_settime_ns`
* :func:`time.monotonic_ns`
* :func:`time.perf_counter_ns`
* :func:`time.process_time_ns`
* :func:`time.time_ns`

Add new clock identifiers:

* :data:`time.CLOCK_BOOTTIME` (Linux): Identical to
Expand Down
20 changes: 19 additions & 1 deletion Include/pytime.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,11 @@ PyAPI_FUNC(_PyTime_t) _PyTime_FromSeconds(int seconds);
((_PyTime_t)(seconds) * (1000 * 1000 * 1000))

/* Create a timestamp from a number of nanoseconds. */
PyAPI_FUNC(_PyTime_t) _PyTime_FromNanoseconds(long long ns);
PyAPI_FUNC(_PyTime_t) _PyTime_FromNanoseconds(_PyTime_t ns);

/* Create a timestamp from nanoseconds (Python int). */
PyAPI_FUNC(int) _PyTime_FromNanosecondsObject(_PyTime_t *t,
PyObject *obj);

/* Convert a number of seconds (Python float or int) to a timetamp.
Raise an exception and return -1 on error, return 0 on success. */
Expand Down Expand Up @@ -114,6 +118,10 @@ PyAPI_FUNC(_PyTime_t) _PyTime_AsMicroseconds(_PyTime_t t,
object. */
PyAPI_FUNC(PyObject *) _PyTime_AsNanosecondsObject(_PyTime_t t);

/* Create a timestamp from a timeval structure.
Raise an exception and return -1 on overflow, return 0 on success. */
PyAPI_FUNC(int) _PyTime_FromTimeval(_PyTime_t *tp, struct timeval *tv);

/* Convert a timestamp to a timeval structure (microsecond resolution).
tv_usec is always positive.
Raise an exception and return -1 if the conversion overflowed,
Expand All @@ -140,12 +148,22 @@ PyAPI_FUNC(int) _PyTime_AsTimevalTime_t(
_PyTime_round_t round);

#if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_KQUEUE)
/* Create a timestamp from a timespec structure.
Raise an exception and return -1 on overflow, return 0 on success. */
PyAPI_FUNC(int) _PyTime_FromTimespec(_PyTime_t *tp, struct timespec *ts);

/* Convert a timestamp to a timespec structure (nanosecond resolution).
tv_nsec is always positive.
Raise an exception and return -1 on error, return 0 on success. */
PyAPI_FUNC(int) _PyTime_AsTimespec(_PyTime_t t, struct timespec *ts);
#endif

/* Compute ticks * mul / div.
The caller must ensure that ((div - 1) * mul) cannot overflow. */
PyAPI_FUNC(_PyTime_t) _PyTime_MulDiv(_PyTime_t ticks,
_PyTime_t mul,
_PyTime_t div);

/* Get the current time from the system clock.

The function cannot fail. _PyTime_Init() ensures that the system clock
Expand Down
17 changes: 17 additions & 0 deletions Lib/test/test_os.py
Original file line number Diff line number Diff line change
Expand Up @@ -3549,6 +3549,23 @@ def test_bad_pathlike(self):
self.assertRaises(ZeroDivisionError, self.fspath,
_PathLike(ZeroDivisionError()))


class TimesTests(unittest.TestCase):
def test_times(self):
times = os.times()
self.assertIsInstance(times, os.times_result)

for field in ('user', 'system', 'children_user', 'children_system',
'elapsed'):
value = getattr(times, field)
self.assertIsInstance(value, float)

if os.name == 'nt':
self.assertEqual(times.children_user, 0)
self.assertEqual(times.children_system, 0)
self.assertEqual(times.elapsed, 0)


# Only test if the C version is provided, otherwise TestPEP519 already tested
# the pure Python implementation.
if hasattr(os, "_fspath"):
Expand Down
24 changes: 23 additions & 1 deletion Lib/test/test_time.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,27 @@ def test_time(self):
self.assertFalse(info.monotonic)
self.assertTrue(info.adjustable)

def test_time_ns_type(self):
def check_ns(sec, ns):
self.assertIsInstance(ns, int)

sec_ns = int(sec * 1e9)
# tolerate a difference of 50 ms
self.assertLess((sec_ns - ns), 50 ** 6, (sec, ns))

check_ns(time.time(),
time.time_ns())
check_ns(time.monotonic(),
time.monotonic_ns())
check_ns(time.perf_counter(),
time.perf_counter_ns())
check_ns(time.process_time(),
time.process_time_ns())

if hasattr(time, 'clock_gettime'):
check_ns(time.clock_gettime(time.CLOCK_REALTIME),
time.clock_gettime_ns(time.CLOCK_REALTIME))

def test_clock(self):
with self.assertWarns(DeprecationWarning):
time.clock()
Expand All @@ -76,7 +97,8 @@ def test_clock(self):
@unittest.skipUnless(hasattr(time, 'clock_gettime'),
'need time.clock_gettime()')
def test_clock_realtime(self):
time.clock_gettime(time.CLOCK_REALTIME)
t = time.clock_gettime(time.CLOCK_REALTIME)
self.assertIsInstance(t, float)

@unittest.skipUnless(hasattr(time, 'clock_gettime'),
'need time.clock_gettime()')
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Implement the :pep:`564`, add new 6 new functions with nanosecond resolution to
the :mod:`time` module: :func:`~time.clock_gettime_ns`,
:func:`~time.clock_settime_ns`, :func:`~time.monotonic_ns`,
:func:`~time.perf_counter_ns`, :func:`~time.process_time_ns`,
:func:`~time.time_ns`.
Loading