Understanding Time.Perf_Counter() and Time.Process_Time()

what is the difference between time.perf_counter() and time.process_time()?

time.perf_counter() keeps going during sleep, time.process_time() does not.

time.perf_counter() → float

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.

time.process_time() → float

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.

See the official documentation

import time

def pc():
start = time.perf_counter()
time.sleep(1)
print(time.perf_counter()-start)

def pt():
start = time.process_time()
time.sleep(1)
print(time.process_time()-start)

pc() # 0.99872320449432
pt() # 0.0

Understanding time.perf_counter() and time.process_time()

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.

Python CPU Clock. time.clock() vs time.perf_counter() vs time.process_time()

Both perf_counter and timeit will give you the time that your block of code tested had taken to perform.

time.process_time() it does not and it calculates what the CPU have taken, which is not necessarily the same as the function or block of code.

I found this thread on Github, seems that the question is quite advanced and may be completely different depending on the OS or program to be benchmark-ed.

Something that time.process_time() is not counting is the Parent Multi-thread:

"One consequence of using time.process_time is that the time spent in child processes of the benchmark is not included. Multithreaded benchmarks also return the total CPU time counting all CPUs."

perf_counter

from time import perf_counter

start = perf_counter()

for _ in range(10000):
x = "-".join(str(n) for n in range(100))
end = perf_counter()
print('Perf Counter= ', end-start)
# Perf Counter= 0.23170840000000004


timeit

import timeit

print(timeit.timeit('"-".join(str(n) for n in range(100))', number=10000))
# 0.20687929999999993

time.perf_counter() or time.process_time() for performance measurements?

The usual way to measure is to use perf counter and repeat the measurement a couple of times.

Process time is not ofently used and I can easily show you why: time.sleep(1) will take 0 seconds according to process time. Every time the process is removed from the scheduler, even if it's due to the code being tested, the process clock won't advance.

May I suggest you to take a look at the built-in timeit module? It uses perf counter as well, and may provide a more comfortable interface for repeated timing.

Edit:

If and only if, your function is entirely CPU bound, does not access external resources, nor cause any system call whatsoever, process_time is the more accurate and better choice.

Is time.process_time() a better measure for performance than time.time()?

I would suggest you use time.perf_counter() as it is the recommended function for this kind of tasks (it auto selects the method with highest precision available).

It returns a float, that means just nothing on its own (unlike the result of time.time()), but computing the difference between two time.perf_counter()'s measurements tells you how much time elapsed.

For more info, read the time.perf_counter()'s docs.

Time variable in script became negative during execution

I doubt this is an 32-bit issue. The third bullet point near the beginning of the Python 3.7 documentation of the time module says:

  • The functions in this module may not handle dates and times before the epoch or far in the future. The cut-off point in the future is determined by the C library; for 32-bit systems, it is typically in 2038.

That said, I don't really know what the problem is. Perhaps using the time.perf_counter() or time.process_time() functions instead would avoid the issue.

How to properly use time.time()

I'd recommend using time.perf_counter instead of time.time, and using timedelta to format the units:

>>> from datetime import timedelta
>>> import time
>>> starttime = time.perf_counter()
>>> x=0
>>> for i in range(100000):
... x+=i
...
>>> duration = timedelta(seconds=time.perf_counter()-starttime)
>>> print('Job took: ', duration)
Job took: 0:00:00.015017

The benefit of using perf_counter is that it won't be impacted by weird things like the timezone or system clock changing while you're measuring, and its resolution is guaranteed to be as high as possible (which may be important if you're timing very quick events).

In either case, the return value is measured in seconds, but you need to know what function it came from in order to know what the float value corresponds to. timedelta is a nicer way to represent a duration than a pure float IMO because it includes the units.



Related Topics



Leave a reply



Submit