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:
Victor Stinner 2017-10-16 15:45:56 +02:00
parent 8a44cd0f3c
commit a4828def40
1 changed files with 83 additions and 9 deletions

View File

@ -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
==================================