This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: time.process_time() constant / erratic on Windows
Type: behavior Stage: resolved
Components: Library (Lib), Windows Versions: Python 3.8, Python 3.7
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: Red Glyph, eryksun, paul.moore, steve.dower, tim.golden, vstinner, zach.ware
Priority: normal Keywords:

Created on 2019-08-14 20:32 by Red Glyph, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Messages (6)
msg349745 - (view) Author: Red Glyph (Red Glyph) Date: 2019-08-14 20:32
Tested with 
- Python 3.7.4, 64-bit, Windows version (installer version)
- python-3.8.0b3-embed-amd64.zip
- python-3.7.2.post1-embed-amd64.zip 
on Windows 7 x64 Professional

time.process_time() always returns the same value. If I check the value of time.process_time_ns(), sometimes it is constant, sometimes I observe a few changes, then it becomes constant too.

Here is a log of an example session, I'm waiting at least 1-2 seconds between each command:

Python 3.7.4 (tags/v3.7.4:e09359112e, Jul  8 2019, 20:34:20) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license()" for more information.
>>> import time
>>> time.process_time()
0.1092007
>>> time.process_time()
0.1092007
>>> time.process_time_ns()
109200700
>>> time.process_time_ns()
124800800
>>> time.process_time_ns()
124800800
>>> time.process_time()
0.1248008
>>> time.process_time()
0.1248008
>>> time.process_time()
0.1248008
>>> time.process_time_ns()
124800800
>>> time.process_time_ns()
124800800
>>> time.process_time_ns()
124800800
>>> time.process_time_ns()
124800800
>>> time.clock()

Warning (from warnings module):
  File "__main__", line 1
DeprecationWarning: time.clock has been deprecated in Python 3.3 and will be removed from Python 3.8: use time.perf_counter or time.process_time instead
77.006126126
>>> time.clock()
79.245575778
>>> time.clock()
80.801103036
>>> time.process_time()
0.1248008
>>>
msg349746 - (view) Author: Zachary Ware (zach.ware) * (Python committer) Date: 2019-08-14 20:47
Try this:

while time.process_time() < 0.5:
    print('.', flush=True, end='')

Or:

>>> time.process_time()
0.03125
>>> len(str(2**500_000))
150515
>>> time.process_time()
0.484375


Basically, process_time() (and process_time_ns()) measure CPU time used by the process, and you aren't making the CPU do anything between your checks.
msg349748 - (view) Author: Red Glyph (Red Glyph) Date: 2019-08-14 20:59
I see that now. The behaviour was different in Linux, though, I suppose it may benefit from a more precise counter, but since in Windows it also has a precise counter with time.perf_counter_ns(), I was expecting to see that value change, but it was mainly a confusion with the older time.clock().

Thanks!
msg349759 - (view) Author: Eryk Sun (eryksun) * (Python triager) Date: 2019-08-14 21:45
> I suppose it may benefit from a more precise counter, but since in 
> Windows it also has a precise counter with time.perf_counter_ns(), 
> I was expecting to see that value change, but it was mainly a 
> confusion with the older time.clock().

Don't read too much into the clock info here:

    >>> time.get_clock_info('process_time').resolution
    1e-07

Process times [1] are stored as a 64-bit integer in units of 100 ns (1e-7). But the kernel schedules threads based on a timer that ticks every 15.625 ms by default. It can be lowered to about 0.5 ms, but this degrades battery life.

[1] https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getprocesstimes
msg349762 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2019-08-14 21:49
> Process times [1] are stored as a 64-bit integer in units of 100 ns (1e-7). But the kernel schedules threads based on a timer that ticks every 15.625 ms by default. It can be lowered to about 0.5 ms, but this degrades battery life.

Patches are welcome to enhance time.get_clock_info() :-)

Don't rely too much on time.get_clock_info() on Linux neither: it basically always say 1 ns, even if the effective resolution is way worse.

See the PEP 418 for some numbers:
https://www.python.org/dev/peps/pep-0418/#process-time

I wrote these programs to write this PEP ;-)

https://github.com/python/peps/tree/master/pep-0418
msg349763 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2019-08-14 21:54
> I see that now. The behaviour was different in Linux, though, I suppose it may benefit from a more precise counter, but since in Windows it also has a precise counter with time.perf_counter_ns(), I was expecting to see that value change, but it was mainly a confusion with the older time.clock().

On Windows, time.clock() was implemented with QueryPerformanceCounter(). This function became time.perf_counter() in Python 3.4. time.clock() was removed. Use time.get_clock_info('perf_counter') ;-)

The PEP 418 introduces new well defined clocks, since time.clock() was not portable.

perf_counter and process_time have very different properties. process_time is stopped when the process sleeps, for example.

https://docs.python.org/dev/library/time.html#time.perf_counter
https://docs.python.org/dev/library/time.html#time.process_time
History
Date User Action Args
2022-04-11 14:59:19adminsetgithub: 82040
2019-08-14 21:54:45vstinnersetmessages: + msg349763
2019-08-14 21:49:29vstinnersetnosy: + vstinner
messages: + msg349762
2019-08-14 21:45:26eryksunsetnosy: + eryksun
messages: + msg349759
2019-08-14 20:59:13Red Glyphsetmessages: + msg349748
2019-08-14 20:48:14zach.waresetstatus: pending -> closed
resolution: not a bug
stage: resolved
2019-08-14 20:47:45zach.waresetstatus: closed -> pending
resolution: not a bug -> (no value)
messages: + msg349746

stage: resolved -> (no value)
2019-08-14 20:44:24Red Glyphsetstatus: open -> closed
resolution: not a bug
stage: resolved
2019-08-14 20:32:41Red Glyphcreate