117

I have some questions about the new functions time.perf_counter() and time.process_time().

For the former, from the documentation:

Return the value (in fractional seconds) of a performance counter, i.e. a clock with the highest available resolution to measure a short duration. It does include time elapsed during sleep and is system-wide. The reference point of the returned value is undefined, so that only the difference between the results of consecutive calls is valid.

Is this 'highest resolution' the same on all systems? Or does it always slightly depend if, for example, we use linux or windows?
The question comes from the fact the reading the documentation of time.time() it says that 'not all systems provide time with a better precision than 1 second' so how can they provide a better and higher resolution now?

About the latter, time.process_time():

Return the value (in fractional seconds) of the sum of the system and user CPU time of the current process. It does not include time elapsed during sleep. It is process-wide by definition. The reference point of the returned value is undefined, so that only the difference between the results of consecutive calls is valid.

I don't understand, what are those 'system time' and 'user CPU time'? What's the difference?

zer0uno
  • 7,521
  • 13
  • 57
  • 86
  • It's more `duck` to use time by function rather than implementation. I.e., use `time.time()` or `time.monotonic()` depending on what you want. – Dima Tisnek Oct 25 '16 at 16:27
  • 3
    See [this comment](https://stackoverflow.com/questions/27863717/why-is-time-clock-giving-a-greater-elapsed-time-than-time-time#comment44277144_27865455) about how all cores used by a process are summed in `time.clock` and `time.process_time`, but child processes are not. Also see [this discussion of precision](https://www.webucator.com/blog/2015/08/python-clocks-explained/) (of course, varies by system). – max Nov 29 '18 at 08:49

1 Answers1

147

There are two distincts types of 'time', in this context: absolute time and relative time.

Absolute time is the 'real-world time', which is returned by time.time() and which we are all used to deal with. It is usually measured from a fixed point in time in the past (e.g. the UNIX epoch of 00:00:00 UTC on 01/01/1970) at a resolution of at least 1 second. Modern systems usually provide milli- or micro-second resolution. It is maintained by the dedicated hardware on most computers, the RTC (real-time clock) circuit is normally battery powered so the system keeps track of real time between power ups. This 'real-world time' is also subject to modifications based on your location (time-zones) and season (daylight savings) or expressed as an offset from UTC (also known as GMT or Zulu time).

Secondly, there is relative time, which is returned by time.perf_counter and time.process_time. This type of time has no defined relationship to real-world time, in the sense that the relationship is system and implementation specific. It can be used only to measure time intervals, i.e. a unit-less value which is proportional to the time elapsed between two instants. This is mainly used to evaluate relative performance (e.g. whether this version of code runs faster than that version of code).

On modern systems, it is measured using a CPU counter which is monotonically increased at a frequency related to CPU's hardware clock. The counter resolution is highly dependent on the system's hardware, the value cannot be reliably related to real-world time or even compared between systems in most cases. Furthermore, the counter value is reset every time the CPU is powered up or reset.

time.perf_counter returns the absolute value of the counter. time.process_time is a value which is derived from the CPU counter but updated only when a given process is running on the CPU and can be broken down into 'user time', which is the time when the process itself is running on the CPU, and 'system time', which is the time when the operating system kernel is running on the CPU on behalf on the process.

mr-sk
  • 13,174
  • 11
  • 66
  • 101
isedev
  • 18,848
  • 3
  • 60
  • 59
  • So in modern computers -> two clocks (i.e. two indipendent circuits), one just manages the real-time, another manages the work of the CPU, that's right? why this division? I mean could't there be just one clock using the assumption, for example, 100 hits of hardware-clock = 1 second ? – zer0uno Sep 11 '14 at 13:35
  • 5
    Real-time runs at a fixed rate, CPU clocks vary widly. Using the CPU clock to measure code performance gives the best possible resolution (down to instruction scale). Limiting the CPU clock to a fixed sub-division of real-time restricts that precision pointlessly. – isedev Sep 11 '14 at 14:03
  • 1
    I don't speak about limiting, I say to derive the real-time from the CPU counter, I mean if I have a 2GHz processor, every time 2bilion of oscillations are made I increase the time of a second – zer0uno Sep 11 '14 at 14:16
  • 5
    how would the OS know about the CPU frequency? about CPU low-power states? who to believe in multi-core systems? And what happens when the CPU is powered off? It is such a difficult task to manage, when having a dedicated, battery power realtime clock circuit is so easy. – isedev Sep 11 '14 at 14:20
  • 1
    @antox: for a better understanding, [read this](https://www.python.org/dev/peps/pep-0418/#glossary) – jfs Feb 14 '15 at 11:46
  • 2
    @isedev: From your answer I understand that time.perf_counter and time.process_time were unitless, but the docs say that they are measured in fractional seconds. That means they can be used to measure time intervals in real world units, right? – elzell Apr 19 '16 at 08:29
  • @elzell: theoretically yes, but it is very hard to do in practice. To get real-world units, one has to keep track of CPU frequency changes, etc..., and that is far from easy to do. – isedev Apr 20 '16 at 21:40
  • Just imagine that you're timing your program late at night, and suddenly daylight savings time rolls the clock back/forward an hour. – mbomb007 Feb 01 '17 at 17:00
  • On Windows, `time.perf_counter()` is not system-wide, it is only process-wide: despite what it says in the docs: It starts at zero for each process. The same is true of `time.perf_counter_ns()`. A solution seems to be `pygame.time.get_ticks()`. – Richard Whitehead Apr 17 '19 at 14:20
  • Absolute time is the 'real-world time' --- is it affected by 'Space-time Bending Theory'? – Lei Yang Jul 25 '19 at 06:00
  • Absolute time is the 'real-world time' --- is it affected by 'Space-time Bending Theory'? – Lei Yang Jul 25 '19 at 06:00
  • 1
    No one has mentioned an important and annoying detail about time.time(): it's not monotonic. The timestamps it produces can and sooner or later will go backwards after your computer resynchronizes its clock over the internet. It's also subject to leap seconds and can jump ahead or behind by a second on those rare occasions when a leap second occurs, once every 18 months or so. – rbasham Feb 27 '21 at 15:41
  • 3
    "This type of time has no defined relationship to real-world time... a unit-less value ..." - Excuse me for my curiosity, but why? It is literally stated in documentation that return value is fractional seconds. – metamaker Sep 10 '21 at 11:21
  • Because there is no standard definition describing how it relates to real-time (implementation specific). It is used to measure and compare intervals only. For instance, the clock/counter may advance only when the process is scheduled on a CPU, etc... and hence have no direct relationship to real-world elapsed time. – isedev Sep 10 '21 at 13:59
  • 2
    However, within the appropriate frame of reference (e.g. executing process), it can be expressed in normal time units and thought of as linear continuous time. – isedev Sep 10 '21 at 14:06
  • To see how long a python programme runs including sleeptime, I use `perf_counter()` and not `process_time` which seems to do the same but without considering sleep. – Timo May 03 '22 at 15:30
  • wrong answer. Perf_counter is TIME, not undefined length ticks, because it is the same as `QueryPerformanceCounter / QueryPerformanceFrequency`, - read MSDN. – iperov Aug 15 '22 at 14:41