[Python-ideas] millisecond and microsecond times without floats

Gregory P. Smith greg at krypto.org
Wed Jun 24 01:32:55 CEST 2015

On Tue, Jun 23, 2015 at 1:25 PM Paul Sokolovsky <pmiscml at gmail.com> wrote:

> Hello,
> On Tue, 23 Jun 2015 00:03:14 +0000
> "Gregory P. Smith" <greg at krypto.org> wrote:
> []
> > > sleep_ms()
> > > sleep_us()
> > > monotonic_ms()
> > > monotonic_us()
> > >
> >
> > If you're going to add new function names, going with the _unit suffix
> > seems best.
> >
> > Another option to consider: keyword only arguments.
> >
> > time.sleep(ms=31416)
> > time.sleep(us=31415927)
> > time.sleep(ns=31415296536)
> That doesn't immediately map to usage for monotonic(), as you mention
> below.
> Another issue is that keywords arguments on average (and for
> MicroPython all the time) are less efficient than positional. Put it
> other way,
> t = monotonic_ns()
> t = monotonic_ns() - t
> is going to give lower number than
> t = monotonic(ns=True)
> t = monotonic(ns=True) - t
> , and the closer it to 0, the better.
> > # We could use the long form names milliseconds, microseconds and
> > nanoseconds but i worry with those that people would inevitably
> > confuse ms with microseconds as times and APIs usually given the
> > standard abbreviations rather than spelled out.
> Another issue is that full spellings are rather long. Logistically,
> while function names can be expected to have autocompletion support,
> keyword arguments not necessarily.
> > time.monotonic(return_int_ns=True) ?
> > # This seems ugly.  time.monotonic_ns() seems better.
> >
> > These should be acceptable to add to Python 3.6 for consistency.
> Well, as I mentioned, I'm personally not looking for this to be
> implemented in CPython right away. Ideally, this should be tested by >1
> independent "embedded" Python implementation first, and only then, based
> on the actual experience, submitted as a PEP. That's rather better than
> "desktop" CPython, which doesn't care about all the subtle "embedded"
> aspects "forced" a way to implement it.
> > I do not think we should have functions for each ms/us/ns unit if
> > adding functions.  Just choose the most useful high precision unit
> > and let people do the math as needed for the others.
> Well, that's one of examples of that "desktop" thinking ;-).
> Consider for example that 2^32 microseconds is just over an hour, so
> expressing everything in microseconds would require arbitrary-precision
> integers, which may be just the same kind of burden for an embedded
> system as floats.
I know. I was actually hoping you'd respond on that point because I haven't
used micropython yet. I assumed it had bignum, or at least fixed "big"
64-bit number, support. But if it does not, having specific functions for
the needed resolutions makes a lot of sense.

> > Point 3 above isn't currently addressed by time module at all.
> > > https://www.python.org/dev/peps/pep-0418/ mentions some internal
> []
> > Reading the PEP my takeaway is that wrap-around of underlying
> > deficient system APIs should be handled by the Python VM for the
> > user. It sounds like we should explicitly spell this out though.
> This is another point which is overlooked by "desktop" programmers -
> time counters can, will, and do wrap around. Big OSes try hard to to
> hide this fact, and indeed succeed well enough, so in cases when they
> do fail, it has shattering effect (at least PR-wise) - Y2K, Y2K38
> problems. For an embedded programmer wrapping counters is objective
> reality, and we wouldn't like to hide that fact in MicroPython
> (of course, only for these, newly introduced real-time precision time
> functions).

I still don't see how an elapsed() function taking two arbitrary integer
arguments could work in a meaningful manner.  Even if you assume they are
the same units, the only assumption that can be made is that if the second
int is lower than the first, at least one wraparound occurred.

> I don't think time.elapsed() could ever provide any utility in either
> > case, just use subtraction.
> Can't work. Previous value of monotonic_us() is 65530, next value is
> 10, what does it tell you?

At least one wrap around occurred. without more information you cannot know
how many.

> time.elapsed() wouldn't know when and
> > where the time values came from and magically be able to apply wrap
> > around or not to them.
> Well, as I mentioned, it's an API contract that elapsed() takes values
> of monotonic_ms(), monotonic_us(), etc. functions, and knows law how
> their values change (likely, apply unsigned power-of-2 modular
> arithmetics). There's additional restriction that this change law for
> all of monotonic_ms(), monotonic_us() is the same, but I personally
> find this an acceptable restriction to not bloat API even further. (But
> it is a restriction, for example, if nano/microsecond time source is
> 24-bit counter, than millisecond time is limited to 24 bits too).

I guess what I'm missing is how you intend to tell elapsed() which of the
_ms vs _us vs _ns functions the values came from. I'm assuming that all
functions are likely to exist at once rather than there being only one high
resolution integer time function.

Given that, yes, you can make elapsed() do what you want.  But I really
think you should call it something more specific than elapsed if the
function is serving as a common source of information on how a particular
type of timer on the system works.  monotonic_elapsed() perhaps?  etc..

Also, agreed, we don't need these in 3.6.  I'm not seeing anything really
objectionable for inclusion in a future 3.x which is all I'm really looking
out for. It sounds like avoiding keyword arguments and adding _ms _us and
_ns variants of functions is the practical solution for micropython.

-gps  (awaiting his WiPys :)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20150623/2eff7e6d/attachment-0001.html>

More information about the Python-ideas mailing list