Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c29b585

Browse files
authored
bpo-31784: Implement PEP 564: add time.time_ns() (#3989)
Add new time functions: * time.clock_gettime_ns() * time.clock_settime_ns() * time.monotonic_ns() * time.perf_counter_ns() * time.process_time_ns() * time.time_ns() Add new _PyTime functions: * _PyTime_FromTimespec() * _PyTime_FromNanosecondsObject() * _PyTime_FromTimeval() Other changes: * Add also os.times() tests to test_os. * pytime_fromtimeval() and pytime_fromtimeval() now return _PyTime_MAX or _PyTime_MIN on overflow, rather than undefined behaviour * _PyTime_FromNanoseconds() parameter type changes from long long to _PyTime_t
1 parent e314853 commit c29b585

9 files changed

Lines changed: 583 additions & 165 deletions

File tree

Doc/library/time.rst

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ Functions
185185
.. versionadded:: 3.3
186186

187187

188-
.. function:: clock_gettime(clk_id)
188+
.. function:: clock_gettime(clk_id) -> float
189189

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

197197

198-
.. function:: clock_settime(clk_id, time)
198+
.. function:: clock_gettime_ns(clk_id) -> int
199+
200+
Similar to :func:`clock_gettime` but return time as nanoseconds.
201+
202+
Availability: Unix.
203+
204+
.. versionadded:: 3.7
205+
206+
207+
.. function:: clock_settime(clk_id, time: float)
199208

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

207216

217+
.. function:: clock_settime_ns(clk_id, time: int)
218+
219+
Similar to :func:`clock_settime` but set time with nanoseconds.
220+
221+
Availability: Unix.
222+
223+
.. versionadded:: 3.7
224+
225+
208226
.. function:: ctime([secs])
209227

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

269287

270-
.. function:: monotonic()
288+
.. function:: monotonic() -> float
271289

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

289307

290-
.. function:: perf_counter()
308+
.. function:: monotonic_ns() -> int
309+
310+
Similar to :func:`monotonic`, but return time as nanoseconds.
311+
312+
.. versionadded:: 3.7
313+
314+
.. function:: perf_counter() -> float
291315

292316
.. index::
293317
single: benchmarking
@@ -300,8 +324,14 @@ Functions
300324

301325
.. versionadded:: 3.3
302326

327+
.. function:: perf_counter_ns() -> int
328+
329+
Similar to :func:`perf_counter`, but return time as nanoseconds.
330+
331+
.. versionadded:: 3.7
303332

304-
.. function:: process_time()
333+
334+
.. function:: process_time() -> float
305335

306336
.. index::
307337
single: CPU time
@@ -316,6 +346,12 @@ Functions
316346

317347
.. versionadded:: 3.3
318348

349+
.. function:: process_time_ns() -> int
350+
351+
Similar to :func:`process_time` but return time as nanoseconds.
352+
353+
.. versionadded:: 3.7
354+
319355
.. function:: sleep(secs)
320356

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

544-
.. function:: time()
580+
.. function:: time() -> float
545581

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

569605

606+
.. function:: time_ns() -> int
607+
608+
Similar to :func:`time` but returns time as an integer number of nanoseconds
609+
since the epoch_.
610+
611+
.. versionadded:: 3.7
612+
570613
.. function:: tzset()
571614

572615
Reset the time conversion rules used by the library routines. The environment

Doc/whatsnew/3.7.rst

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,32 @@ effort will be made to add such support.
159159
PEP written by Erik M. Bray; implementation by Masayuki Yamamoto.
160160

161161

162+
PEP 564: Add new time functions with nanosecond resolution
163+
----------------------------------------------------------
164+
165+
Add six new "nanosecond" variants of existing functions to the :mod:`time`
166+
module:
167+
168+
* :func:`time.clock_gettime_ns`
169+
* :func:`time.clock_settime_ns`
170+
* :func:`time.monotonic_ns`
171+
* :func:`time.perf_counter_ns`
172+
* :func:`time.process_time_ns`
173+
* :func:`time.time_ns`
174+
175+
While similar to the existing functions without the ``_ns`` suffix, they
176+
provide nanosecond resolution: they return a number of nanoseconds as a Python
177+
``int``.
178+
179+
The ``time.time_ns()`` resolution is 3 times better than the ``time.time()``
180+
resolution on Linux and Windows.
181+
182+
.. seealso::
183+
184+
:pep:`564` -- Add new time functions with nanosecond resolution
185+
PEP written and implemented by Victor Stinner
186+
187+
162188
Other Language Changes
163189
======================
164190

@@ -313,6 +339,15 @@ separately. (Contributed by Barry Warsaw in :issue:`1198569`.)
313339
time
314340
----
315341

342+
The :pep:`564` added six new functions with nanosecond resolution:
343+
344+
* :func:`time.clock_gettime_ns`
345+
* :func:`time.clock_settime_ns`
346+
* :func:`time.monotonic_ns`
347+
* :func:`time.perf_counter_ns`
348+
* :func:`time.process_time_ns`
349+
* :func:`time.time_ns`
350+
316351
Add new clock identifiers:
317352

318353
* :data:`time.CLOCK_BOOTTIME` (Linux): Identical to

Include/pytime.h

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,11 @@ PyAPI_FUNC(_PyTime_t) _PyTime_FromSeconds(int seconds);
8585
((_PyTime_t)(seconds) * (1000 * 1000 * 1000))
8686

8787
/* Create a timestamp from a number of nanoseconds. */
88-
PyAPI_FUNC(_PyTime_t) _PyTime_FromNanoseconds(long long ns);
88+
PyAPI_FUNC(_PyTime_t) _PyTime_FromNanoseconds(_PyTime_t ns);
89+
90+
/* Create a timestamp from nanoseconds (Python int). */
91+
PyAPI_FUNC(int) _PyTime_FromNanosecondsObject(_PyTime_t *t,
92+
PyObject *obj);
8993

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

121+
/* Create a timestamp from a timeval structure.
122+
Raise an exception and return -1 on overflow, return 0 on success. */
123+
PyAPI_FUNC(int) _PyTime_FromTimeval(_PyTime_t *tp, struct timeval *tv);
124+
117125
/* Convert a timestamp to a timeval structure (microsecond resolution).
118126
tv_usec is always positive.
119127
Raise an exception and return -1 if the conversion overflowed,
@@ -140,12 +148,22 @@ PyAPI_FUNC(int) _PyTime_AsTimevalTime_t(
140148
_PyTime_round_t round);
141149

142150
#if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_KQUEUE)
151+
/* Create a timestamp from a timespec structure.
152+
Raise an exception and return -1 on overflow, return 0 on success. */
153+
PyAPI_FUNC(int) _PyTime_FromTimespec(_PyTime_t *tp, struct timespec *ts);
154+
143155
/* Convert a timestamp to a timespec structure (nanosecond resolution).
144156
tv_nsec is always positive.
145157
Raise an exception and return -1 on error, return 0 on success. */
146158
PyAPI_FUNC(int) _PyTime_AsTimespec(_PyTime_t t, struct timespec *ts);
147159
#endif
148160

161+
/* Compute ticks * mul / div.
162+
The caller must ensure that ((div - 1) * mul) cannot overflow. */
163+
PyAPI_FUNC(_PyTime_t) _PyTime_MulDiv(_PyTime_t ticks,
164+
_PyTime_t mul,
165+
_PyTime_t div);
166+
149167
/* Get the current time from the system clock.
150168
151169
The function cannot fail. _PyTime_Init() ensures that the system clock

Lib/test/test_os.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3549,6 +3549,23 @@ def test_bad_pathlike(self):
35493549
self.assertRaises(ZeroDivisionError, self.fspath,
35503550
_PathLike(ZeroDivisionError()))
35513551

3552+
3553+
class TimesTests(unittest.TestCase):
3554+
def test_times(self):
3555+
times = os.times()
3556+
self.assertIsInstance(times, os.times_result)
3557+
3558+
for field in ('user', 'system', 'children_user', 'children_system',
3559+
'elapsed'):
3560+
value = getattr(times, field)
3561+
self.assertIsInstance(value, float)
3562+
3563+
if os.name == 'nt':
3564+
self.assertEqual(times.children_user, 0)
3565+
self.assertEqual(times.children_system, 0)
3566+
self.assertEqual(times.elapsed, 0)
3567+
3568+
35523569
# Only test if the C version is provided, otherwise TestPEP519 already tested
35533570
# the pure Python implementation.
35543571
if hasattr(os, "_fspath"):

Lib/test/test_time.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,27 @@ def test_time(self):
6464
self.assertFalse(info.monotonic)
6565
self.assertTrue(info.adjustable)
6666

67+
def test_time_ns_type(self):
68+
def check_ns(sec, ns):
69+
self.assertIsInstance(ns, int)
70+
71+
sec_ns = int(sec * 1e9)
72+
# tolerate a difference of 50 ms
73+
self.assertLess((sec_ns - ns), 50 ** 6, (sec, ns))
74+
75+
check_ns(time.time(),
76+
time.time_ns())
77+
check_ns(time.monotonic(),
78+
time.monotonic_ns())
79+
check_ns(time.perf_counter(),
80+
time.perf_counter_ns())
81+
check_ns(time.process_time(),
82+
time.process_time_ns())
83+
84+
if hasattr(time, 'clock_gettime'):
85+
check_ns(time.clock_gettime(time.CLOCK_REALTIME),
86+
time.clock_gettime_ns(time.CLOCK_REALTIME))
87+
6788
def test_clock(self):
6889
with self.assertWarns(DeprecationWarning):
6990
time.clock()
@@ -76,7 +97,8 @@ def test_clock(self):
7697
@unittest.skipUnless(hasattr(time, 'clock_gettime'),
7798
'need time.clock_gettime()')
7899
def test_clock_realtime(self):
79-
time.clock_gettime(time.CLOCK_REALTIME)
100+
t = time.clock_gettime(time.CLOCK_REALTIME)
101+
self.assertIsInstance(t, float)
80102

81103
@unittest.skipUnless(hasattr(time, 'clock_gettime'),
82104
'need time.clock_gettime()')
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Implement the :pep:`564`, add new 6 new functions with nanosecond resolution to
2+
the :mod:`time` module: :func:`~time.clock_gettime_ns`,
3+
:func:`~time.clock_settime_ns`, :func:`~time.monotonic_ns`,
4+
:func:`~time.perf_counter_ns`, :func:`~time.process_time_ns`,
5+
:func:`~time.time_ns`.

0 commit comments

Comments
 (0)