Complete PEP 564
* Add "Issues caused by precision loss" section with two examples * Alternatives: add new "Modify time.time() result type" and "New time_ns module" sections
This commit is contained in:
parent
8a44cd0f3c
commit
a4828def40
92
pep-0564.rst
92
pep-0564.rst
|
@ -80,6 +80,43 @@ The PEP was rejected for different reasons:
|
|||
to adapt code to handle it.
|
||||
|
||||
|
||||
Issues caused by precision loss
|
||||
-------------------------------
|
||||
|
||||
Example 1: measure time delta
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
A server is running for longer than 104 days. A clock is read before
|
||||
and after running a function to measure its performance. This benchmark
|
||||
lose precision only because the float type used by clocks, not because
|
||||
of the clock resolution.
|
||||
|
||||
On Python microbenchmarks, it is common to see function calls taking
|
||||
less than 100 ns. A difference of a single nanosecond becomes
|
||||
significant.
|
||||
|
||||
Example 2: compare time with different resolution
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Two programs "A" and "B" are runing on the same system, so use the system
|
||||
block. The program A reads the system clock with nanosecond resolution
|
||||
and writes the timestamp with nanosecond resolution. The program B reads
|
||||
the timestamp with nanosecond resolution, but compares it to the system
|
||||
clock read with a worse resolution. To simplify the example, let's say
|
||||
that it reads the clock with second resolution. If that case, there is a
|
||||
window of 1 second while the program B can see the timestamp written by A
|
||||
as "in the future".
|
||||
|
||||
Nowadays, more and more databases and filesystems support storing time
|
||||
with nanosecond resolution.
|
||||
|
||||
.. note::
|
||||
This issue was already fixed for file modification time by adding the
|
||||
``st_mtime_ns`` field to the ``os.stat()`` result, and by accepting
|
||||
nanoseconds in ``os.utime()``. This PEP proposes to generalize the
|
||||
fix.
|
||||
|
||||
|
||||
CPython enhancements of the last 5 years
|
||||
----------------------------------------
|
||||
|
||||
|
@ -187,24 +224,37 @@ UNIX epoch as reference, this type supports time since year 1677 to year
|
|||
>>> 1970 + 2 ** 63 / (10 ** 9 * 3600 * 24 * 365.25)
|
||||
2262.271023045313
|
||||
|
||||
Modify time.time() result type
|
||||
------------------------------
|
||||
|
||||
It was proposed to modify ``time.time()`` to return a different float
|
||||
type with better precision.
|
||||
|
||||
The PEP 410 proposed to use ``decimal.Decimal`` which already exists and
|
||||
supports arbitray precision, but it was rejected. Apart
|
||||
``decimal.Decimal``, no portable ``float`` type with better precision is
|
||||
currently available in Python.
|
||||
|
||||
Changing the builtin Python ``float`` type is out of the scope of this
|
||||
PEP.
|
||||
|
||||
Moreover, changing existing functions to return a new type introduces a
|
||||
risk of breaking the backward compatibility even the new type is
|
||||
designed carefully.
|
||||
|
||||
|
||||
Different types
|
||||
---------------
|
||||
|
||||
It was proposed to modify ``time.time()`` to use float type with better
|
||||
precision. The PEP 410 proposed to use ``decimal.Decimal``, but it was
|
||||
rejected. Apart ``decimal.Decimal``, no portable ``float`` type with
|
||||
better precision is currently available in Python. Changing the builtin
|
||||
Python ``float`` type is out of the scope of this PEP.
|
||||
|
||||
Other ideas of new types were proposed to support larger or arbitrary
|
||||
Many ideas of new types were proposed to support larger or arbitrary
|
||||
precision: fractions, structures or 2-tuple using integers,
|
||||
fixed-precision floating point number, etc.
|
||||
|
||||
See also the PEP 410 for a previous long discussion on other types.
|
||||
|
||||
Adding a new type requires more effort to support it, than reusing
|
||||
``int``. The standard library, third party code and applications would
|
||||
have to be modified to support it.
|
||||
the existing ``int`` type. The standard library, third party code and
|
||||
applications would have to be modified to support it.
|
||||
|
||||
The Python ``int`` type is well known, well supported, ease to
|
||||
manipulate, and supports all arithmetic operations like:
|
||||
|
@ -233,6 +283,30 @@ seconds (``time.time()`` returning ``float``) and nanoseconds
|
|||
there is no need for resolution better than 1 nanosecond in practive in
|
||||
the Python standard library.
|
||||
|
||||
New time_ns module
|
||||
------------------
|
||||
|
||||
Add a new ``time_ns`` module which contains the five new functions:
|
||||
|
||||
* ``time_ns.clock_gettime(clock_id)``
|
||||
* ``time_ns.clock_settime(clock_id, time: int)``
|
||||
* ``time_ns.perf_counter()``
|
||||
* ``time_ns.monotonic()``
|
||||
* ``time_ns.time()``
|
||||
|
||||
The first question is if the ``time_ns`` should expose exactly the same
|
||||
API (constants, functions, etc.) than the ``time`` module. It can be
|
||||
painful to maintain two flavors of the ``time`` module. How users use
|
||||
suppose to make a choice between these two modules?
|
||||
|
||||
If tomorrow, other nanosecond variant are needed in the ``os`` module,
|
||||
will we have to add a new ``os_ns`` module as well? There are functions
|
||||
related to time in many modules: ``time``, ``os``, ``signal``,
|
||||
``resource``, ``select``, etc.
|
||||
|
||||
Another idea is to add a ``time.ns`` submodule or a nested-namespace to
|
||||
get the ``time.ns.time()`` syntax.
|
||||
|
||||
|
||||
Annex: Clocks Resolution in Python
|
||||
==================================
|
||||
|
|
Loading…
Reference in New Issue