[Python-Dev] an alternative to embedding policy in PEP 418 (was: PEP 418: Add monotonic clock)

Victor Stinner victor.stinner at gmail.com
Wed Apr 4 01:45:27 CEST 2012


> | get_clock() returns None if no clock has the requested flags, whereas
> | I expected an exception (LookupError or NotImplementError?).
>
> That is deliberate. People can easily write fallback like this:
>
>  clock = get_clock(T_MONOTONIC|T_HIRES) or get_clock(T_MONOTONIC)

Why not passing a a list of set of flags? Example:

haypo_steady = get_clock(MONOTONIC|STEADY, STEADY, MONOTONIC, REALTIME)
# try to get a monotonic and steady clock,
# or fallback to a steady clock,
# or fallback to a monotonic clock,
# or fallback to the system clock

haypo_perf_counter = get_clock(HIGHRES, MONOTONIC|STEADY, STEADY,
MONOTONIC, REALTIME)
# try to get a high-resolution clock
# or fallback to a monotonic and steady clock,
# or fallback to a steady clock,
# or fallback to a monotonic clock,
# or fallback to the system clock

On Windows, haypo_steady should give GetTickCount (MONOTONIC|STEADY)
and haypo_perf_counter should give QueryPerformanceCounter
(MONOTONIC|HIGHRES).

Hum, I'm not sure that haypo_highres uses the same clocks than
time.perf_counter() in the PEP.

> If one wants an exception it is easy to follow up with:
>
>  if not clock:
>    raise RunTimeError("no suitable clocks on offer on this platform")

And if don't read the doc carefuly and forget the test, you can a
"NoneType object is not callable" error.

> | get_clock() doesn't remember if a clock works or not (if it raises an
> | OSError) and does not fallback to the next clock on error. See
> | "pseudo-codes" in the PEP 418.
>
> I presume the available clocks are all deduced from the platform. Your
> pseudo code checks for OSError at fetch-the-clock time. I expect that
> to occur once when the module is loaded, purely to populate the table
> of avaiable platform clocks.

It's better to avoid unnecessary system calls at startup (when the
time module is loaded), but you may defer the creation of the clock
list, or at least of the flags of each clock.

> Note that you don't need to provide a clock list at all; get_clock(0
> will use ALL_CLOCKS by default, and hires() and monotonic() should each
> have their own default list.

A list of clocks and a function are maybe redundant. Why not only
providing a function?

> Regarding the choice itself: as the _caller_ (not the library author),
> you must decide what you want most. You're already planning offering
> monotonic() and hires() calls without my proposal!

My PEP starts with use cases: it proposes one clock per use case.
There is no "If you need a monotonic, steady and high-resolution clock
..." use case.

The "highres" name was confusing, I just replaced it with
time.perf_counter() (thanks Antoine for the name!).
time.perf_counter() should be used for benchmarking and profiling.

> Taking your query "Should
> I use MONTONIC_CLOCKS or HIRES_CLOCKS when I would like a monotonic and
> high-resolution clock" is _already_ a problem. Of course you must call
> monotonic() or hires() first under the current scheme, and must answer this
> question anyway. Do you prefer hires? Use it first! No preference? Then the
> question does not matter.

I mean having to choose the flags *and* the list of clocks is hard. I
would prefer to only have to choose flags or only the list of clocks.
The example was maybe not the best one.

> | If you have only one list of clocks, how do sort the list to get
> | QueryPerformanceCounter when the user asks for highres and
> | GetTickCount when the user asks for monotonic?
>
> This is exactly why there are supposed to be different lists.
> You have just argued against your objection above.

You can solve this issue with only one list of clocks if you use the
right set of flags.

> | So we would have:
> |
> | GetTickCount.flags = T_MONOTONIC | T_STEADY | T_HIGHRES
> |
> | Even if GetTickCount has only an accuracy of 15 ms :-/
>
> T_HIGHRES is a quality call, surely? If 15ms is too sloppy for a "high
> resolution, the is should _not_ have the T_HIRES flag.

So what is the minimum resolution and/or accuracy of the HIGHRES flag?

> | Could you please update your code according to my remarks? I will try
> | to integrate it into the PEP. A PEP should list all alternatives!
>
> Surely.
>
> The only updates I can see are to provide the flat interface
> (instead of via clock-object indirection) and the missing hires_clock()
> and monotonic_clock() convenience methods.

A full implementation would help to decide which API is the best one.
"Full" implementation:

 - define all convinience function
 - define all list of clocks
 - define flags of all clocks listed in the PEP 418: clocks used in
the pseudo-code of time.steady and time.perf_counter, and maybe also
time.time

Victor


More information about the Python-Dev mailing list