0

I just tried the following little Python3 test:

import time
tvar = 1
tsa = time.time()
tvar += 1
tsb = time.time()
print("tsb {} tsa {} tsb-tsa {}".format(tsb, tsa, tsb-tsa))
print("  rate {}".format(tvar/(tsb-tsa)))
tsc = time.monotonic()
tvar += 1
tsd = time.monotonic()
print("tsd {} tsc {} tsd-tsc {}".format(tsd, tsc, tsd-tsc))
print("  rate {}".format(tvar/(tsd-tsc)))

If I run this under https://replit.com/languages/python3 - then the script completes fine, and results I get are more-less expected:

tsb 1675886955.5210621 tsa 1675886955.5210614 tsb-tsa 7.152557373046875e-07
  rate 2796202.6666666665
tsd 23325.72801936 tsc 23325.728018751 tsd-tsc 6.090012902859598e-07
  rate 4926097.937479465

However, when I run the very same script under Python3 in MINGW64 shell (MSYS2 on Windows 10) which is currently version Python 3.10.9, the script actually crashes:

$ python3 test_time.py
tsb 1675887125.3224628 tsa 1675887125.3224628 tsb-tsa 0.0
Traceback (most recent call last):
  File "D:\msys64\tmp\test\test_time.py", line 7, in <module>
    print("  rate {}".format(tvar/(tsb-tsa)))
ZeroDivisionError: float division by zero

So, here the tsb and tsa timestamps ended up being equal, even if they are called separated by an assignment command (tvar += 1) - but even if the timestamp assignments were called one after the other, they should have shown a different value?

And the same problems appears with time.monotonic() as well (although the above example crashes before we get to that point).

So, is this Python3 behavior (i.e. on some platforms, time.time() or time.monotonic() can be called two times in a row, and return the exact same timestamp) expected; and is there anything I can do, to have timestamp behavior consistent across platforms (that is, at least: two subsequent (quick) calls to time.time() or time.monotonic() should result with not just differing timestamps, but with timestamps where the earlier timestamp is a smaller numeric value than later timestamp? (so that durations/time differences can never result with zero, which would otherwise cause division by zero when calculating rates)

sdbbs
  • 4,270
  • 5
  • 32
  • 87
  • 1
    Any reason you're not using `timeit`? – Barmar Feb 08 '23 at 20:31
  • 3
    If the system's clock granularity is not small enough, you can call `time.time()` multiple times without the clock changing. `time.monotonic()` guarantees that it won't go backwards, but it doesn't promise that it will always increase each time. – Barmar Feb 08 '23 at 20:33
  • Thanks @Barmar - as far as I know, `timeit` is used to "measure execution time of small code snippets", but I don't want to really measure execution time of small snippets - I want to measure e.g. transfer rates I get over USB or network; but I'm keen to see an example of how to use `timeit` in that case. – sdbbs Feb 08 '23 at 20:33
  • Thanks @Barmar - the "doesn't promise that it will always increase each time" explains why also `time.monotonic()` might fail, which really suprised me at first; good to know this! – sdbbs Feb 08 '23 at 20:34
  • 1
    OK, then you need to repeat your data transfer enough times that the clock changes. – Barmar Feb 08 '23 at 20:35
  • 2
    In general, when you're trying to time anything, you need to measure multiple repetitions or process a large input and calculate the average. Otherwise random variation will make the results meaningless. – Barmar Feb 08 '23 at 20:37
  • https://stackoverflow.com/questions/1938048/high-precision-clock-in-python – lex Feb 09 '23 at 04:34

0 Answers0