This PEP proposes to addtime.get_clock_info(name),time.monotonic(),time.perf_counter() andtime.process_time() functions to Python 3.3.
If a program uses the system time to schedule events or to implementa timeout, it may fail to run events at the right moment or stop thetimeout too early or too late when the system time is changed manually oradjusted automatically by NTP. A monotonic clock should be usedinstead to not be affected by system time updates:time.monotonic().
To measure the performance of a function,time.clock() can be usedbut it is very different on Windows and on Unix. On Windows,time.clock() includes time elapsed during sleep, whereas it doesnot on Unix.time.clock() resolution is very good on Windows, butvery bad on Unix. The newtime.perf_counter() function should beused instead to always get the most precise performance counter with aportable behaviour (ex: include time spend during sleep).
Until now, Python did not provide directly a portablefunction to measure CPU time.time.clock() can be used on Unix,but it has badresolution.resource.getrusage() oros.times() can also beused on Unix, but they require to compute the sum of timespent in kernel space and user space. The newtime.process_time()function acts as a portable counter that always measures CPU time(excluding time elapsed during sleep) and has the best availableresolution.
Each operating system implements clocks and performance countersdifferently, and it is useful to know exactly which function is usedand some properties of the clock like its resolution. The newtime.get_clock_info() function gives access to all availableinformation about each Python time function.
New functions:
time.monotonic(): timeout and scheduling, not affected by systemclock updatestime.perf_counter(): benchmarking, most precise clock for shortperiodtime.process_time(): profiling, CPU time of the processUsers of new functions:
Thetime.clock() function is deprecated because it is notportable: it behaves differently depending on the operating system.time.perf_counter() ortime.process_time() should be usedinstead, depending on your requirements.time.clock() is marked asdeprecated but is not planned for removal.
Limitations:
CLOCK_MONOTONIC is slewed on Linux, whereasGetTickCount() is not adjusted on Windows.time.get_clock_info('monotonic')['adjustable'] can be used to checkif the monotonic clock is adjustable or not.time.clock_gettime(CLOCK_THREAD_CPUTIME_ID). On Windows, ctypes oranother module can be used to call theGetThreadTimes()function.Get information on the specified clock. Supported clock names:
"clock":time.clock()"monotonic":time.monotonic()"perf_counter":time.perf_counter()"process_time":time.process_time()"time":time.time()Return atime.clock_info object which has the following attributes:
implementation (str): name of the underlying operating systemfunction. Examples:"QueryPerformanceCounter()","clock_gettime(CLOCK_REALTIME)".monotonic (bool): True if the clock cannot go backward.adjustable (bool):True if the clock can be changed automatically(e.g. by a NTP daemon) or manually by the system administrator,Falseotherwiseresolution (float): resolution in seconds of the clock.Monotonic clock, i.e. cannot go backward. It is not affected by systemclock updates. The reference point of the returned value isundefined, so that only the difference between the results ofconsecutive calls is valid and is a number of seconds.
On Windows versions older than Vista,time.monotonic() detectsGetTickCount() integer overflow (32 bits, roll-over after 49.7days). It increases an internal epoch (reference time by) 232 each time that an overflow is detected. The epoch is storedin the process-local state and sothe value oftime.monotonic() may be different in two Pythonprocesses running for more than 49 days. On more recent versions ofWindows and on other operating systems,time.monotonic() issystem-wide.
Availability: Windows, Mac OS X, Linux, FreeBSD, OpenBSD, Solaris.Not available on GNU/Hurd.
Pseudo-code[2]:
ifos.name=='nt':# GetTickCount64() requires Windows Vista, Server 2008 or laterifhasattr(_time,'GetTickCount64'):defmonotonic():return_time.GetTickCount64()*1e-3else:defmonotonic():ticks=_time.GetTickCount()ifticks<monotonic.last:# Integer overflow detectedmonotonic.delta+=2**32monotonic.last=ticksreturn(ticks+monotonic.delta)*1e-3monotonic.last=0monotonic.delta=0elifsys.platform=='darwin':defmonotonic():ifmonotonic.factorisNone:factor=_time.mach_timebase_info()monotonic.factor=timebase[0]/timebase[1]*1e-9return_time.mach_absolute_time()*monotonic.factormonotonic.factor=Noneelifhasattr(time,"clock_gettime")andhasattr(time,"CLOCK_HIGHRES"):defmonotonic():returntime.clock_gettime(time.CLOCK_HIGHRES)elifhasattr(time,"clock_gettime")andhasattr(time,"CLOCK_MONOTONIC"):defmonotonic():returntime.clock_gettime(time.CLOCK_MONOTONIC)
On Windows,QueryPerformanceCounter() is not used even though ithas a better resolution thanGetTickCount(). It is not reliableand has too many issues.
Performance counter with the highest available resolution to measure ashort duration. It does include time elapsed during sleep and issystem-wide. The reference point of the returned value is undefined,so that only the difference between the results of consecutive callsis valid and is a number of seconds.
It is available on all platforms.
Pseudo-code:
ifos.name=='nt':def_win_perf_counter():if_win_perf_counter.frequencyisNone:_win_perf_counter.frequency=_time.QueryPerformanceFrequency()return_time.QueryPerformanceCounter()/_win_perf_counter.frequency_win_perf_counter.frequency=Nonedefperf_counter():ifperf_counter.use_performance_counter:try:return_win_perf_counter()exceptOSError:# QueryPerformanceFrequency() fails if the installed# hardware does not support a high-resolution performance# counterperf_counter.use_performance_counter=Falseifperf_counter.use_monotonic:# The monotonic clock is preferred over the system timetry:returntime.monotonic()exceptOSError:perf_counter.use_monotonic=Falsereturntime.time()perf_counter.use_performance_counter=(os.name=='nt')perf_counter.use_monotonic=hasattr(time,'monotonic')
Sum of the system and user CPU time of the current process. It doesnot include time elapsed during sleep. It is process-wide bydefinition. The reference point of the returned value is undefined,so that only the difference between the results of consecutive callsis valid.
It is available on all platforms.
Pseudo-code[2]:
ifos.name=='nt':defprocess_time():handle=_time.GetCurrentProcess()process_times=_time.GetProcessTimes(handle)return(process_times['UserTime']+process_times['KernelTime'])*1e-7else:try:importresourceexceptImportError:has_resource=Falseelse:has_resource=Truedefprocess_time():ifprocess_time.clock_idisnotNone:try:returntime.clock_gettime(process_time.clock_id)exceptOSError:process_time.clock_id=Noneifprocess_time.use_getrusage:try:usage=resource.getrusage(resource.RUSAGE_SELF)returnusage[0]+usage[1]exceptOSError:process_time.use_getrusage=Falseifprocess_time.use_times:try:times=_time.times()cpu_time=times.tms_utime+times.tms_stimereturncpu_time/process_time.ticks_per_secondsexceptOSError:process_time.use_getrusage=Falsereturn_time.clock()if(hasattr(time,'clock_gettime')andhasattr(time,'CLOCK_PROF')):process_time.clock_id=time.CLOCK_PROFelif(hasattr(time,'clock_gettime')andhasattr(time,'CLOCK_PROCESS_CPUTIME_ID')):process_time.clock_id=time.CLOCK_PROCESS_CPUTIME_IDelse:process_time.clock_id=Noneprocess_time.use_getrusage=has_resourceprocess_time.use_times=hasattr(_time,'times')ifprocess_time.use_times:# sysconf("SC_CLK_TCK"), or the HZ constant, or 60process_time.ticks_per_seconds=_times.ticks_per_seconds
The system time which is usually the civil time. It is system-wide bydefinition. It can be set manually by the system administrator orautomatically by a NTP daemon.
It is available on all platforms and cannot fail.
Pseudo-code[2]:
ifos.name=="nt":deftime():return_time.GetSystemTimeAsFileTime()else:deftime():ifhasattr(time,"clock_gettime"):try:returntime.clock_gettime(time.CLOCK_REALTIME)exceptOSError:# CLOCK_REALTIME is not supported (unlikely)passifhasattr(_time,"gettimeofday"):try:return_time.gettimeofday()exceptOSError:# gettimeofday() should not failpassifhasattr(_time,"ftime"):return_time.ftime()else:return_time.time()
Suspend execution for the given number of seconds. The actualsuspension time may be less than that requested because any caughtsignal will terminate thetime.sleep() following execution of thatsignal’s catching routine. Also, the suspension time may be longerthan requested by an arbitrary amount because of the scheduling ofother activity in the system.
Pseudo-code[2]:
try:importselectexceptImportError:has_select=Falseelse:has_select=hasattr(select,"select")ifhas_select:defsleep(seconds):returnselect.select([],[],[],seconds)elifhasattr(_time,"delay"):defsleep(seconds):milliseconds=int(seconds*1000)_time.delay(milliseconds)elifos.name=="nt":defsleep(seconds):milliseconds=int(seconds*1000)win32api.ResetEvent(hInterruptEvent);win32api.WaitForSingleObject(sleep.sigint_event,milliseconds)sleep.sigint_event=win32api.CreateEvent(NULL,TRUE,FALSE,FALSE)# SetEvent(sleep.sigint_event) will be called by the signal handler of SIGINTelifos.name=="os2":defsleep(seconds):milliseconds=int(seconds*1000)DosSleep(milliseconds)else:defsleep(seconds):seconds=int(seconds)_time.sleep(seconds)
On Unix, return the current processor time as a floating point numberexpressed in seconds. It is process-wide by definition. The resolution,and in fact the very definition of the meaning of “processor time”,depends on that of the C function of the same name, but in any case,this is the function to use for benchmarking Python or timingalgorithms.
On Windows, this function returns wall-clock seconds elapsed since thefirst call to this function, as a floating point number, based on theWin32 functionQueryPerformanceCounter(). The resolution istypically better than one microsecond. It is system-wide.
Pseudo-code[2]:
ifos.name=='nt':defclock():try:return_win_perf_counter()exceptOSError:# QueryPerformanceFrequency() fails if the installed# hardware does not support a high-resolution performance# counterpassreturn_time.clock()else:clock=_time.clock
The name “time.try_monotonic()” was also proposed for an olderversion of time.monotonic() which would fall back to the systemtime when no monotonic clock was available.
To not have to define high-level clocks, which is a difficult task, asimpler approach is to only expose operating system clocks.time.clock_gettime() and related clock identifiers were already addedto Python 3.3 for example.
If no monotonic clock is available, time.monotonic() falls back to thesystem time.
Issues:
Different APIs were proposed to define such function.
A keyword argument that gets passed as a constant in the caller isusually poor API.
Raising NotImplementedError for a function is something uncommon inPython and should be avoided.
time.monotonic() returns (time: float, is_monotonic: bool).
An alternative is to use a function attribute:time.monotonic.is_monotonic. The attribute value would be None beforethe first call to time.monotonic().
The PEP as proposed offers a few new clocks, but their guaranteesare deliberately loose in order to offer useful clocks on differentplatforms. This inherently embeds policy in the calls, and thecaller must thus choose a policy.
The “choose a clock” approach suggests an additional API to letcallers implement their own policy if necessaryby making most platform clocks available and letting the caller pick amongst them.The PEP’s suggested clocks are still expected to be available for the commonsimple use cases.
To do this two facilities are needed:an enumeration of clocks, and metadata on the clocks to enable the user toevaluate their suitability.
The primary interface is a function make simple choices easy:the caller can usetime.get_clock(*flags) with some combination of flags.This includes at least:
It returns a clock object with a .now() method returning the current time.The clock object is annotated with metadata describing the clock feature set;its .flags field will contain at least all the requested flags.
time.get_clock() returns None if no matching clock is found and so calls canbe chained using the or operator. Example of a simple policy decision:
T=get_clock(MONOTONIC)orget_clock(STEADY)orget_clock()t=T.now()
The available clocks always at least include a wrapper fortime.time(),so a final call with no flags can always be used to obtain a working clock.
Examples of flags of system clocks:
The clock objects contain other metadata including the clock flagswith additional feature flags above those listed above, the nameof the underlying OS facility, and clock precisions.
time.get_clock() still chooses a single clock; an enumerationfacility is also required.The most obvious method is to offertime.get_clocks() with thesame signature astime.get_clock(), but returning a sequenceof all clocks matching the requested flags.Requesting no flags would thus enumerate all available clocks,allowing the caller to make an arbitrary choice amongst them basedon their metadata.
Example partial implementation:clockutils.py.
Should Python ensure that a monotonic clock is trulymonotonic by computing the maximum with the clock value and theprevious value?
Since it’s relatively straightforward to cache the last value returnedusing a static variable, it might be interesting to use this to makesure that the values returned are indeed monotonic.
Python may only work around a specific known operating system bug:KB274323 contains a code example to workaround the bug (useGetTickCount() to detect QueryPerformanceCounter() leap).
Issues with “correcting” non-monotonicities:
time.localtime() andtime.gmtime(). Not changed by thisPEP.There were 4 implementations of the time in the Linux kernel: UTIME(1996), timer wheel (1997), HRT (2001) and hrtimers (2007). Thelatter is the result of the “high-res-timers” project started byGeorge Anzinger in 2001, with contributions by Thomas Gleixner andDouglas Niehaus. The hrtimers implementation was merged into Linux2.6.21, released in 2007.
hrtimers supports various clock sources. It sets a priority to eachsource to decide which one will be used. Linux supports the followingclock sources:
High-resolution timers are not supported on all hardwarearchitectures. They are at least provided on x86/x86_64, ARM andPowerPC.
clock_getres() returns 1 nanosecond forCLOCK_REALTIME andCLOCK_MONOTONIC regardless of underlying clock source. ReadRe:clock_getres() and real resolution from Thomas Gleixner (9 Feb2012) for an explanation.
The/sys/devices/system/clocksource/clocksource0 directorycontains two useful files:
available_clocksource: list of available clock sourcescurrent_clocksource: clock source currently used. It ispossible to change the current clocksource by writing the name of aclocksource into this file./proc/timer_list contains the list of all hardware timers.
Read also thetime(7) manual page:“overview of time and timers”.
kern.timecounter.choice lists available hardware clocks with theirpriority. The sysctl program can be used to change the timecounter.Example:
# dmesg | grep TimecounterTimecounter"i8254"frequency1193182Hzquality0Timecounter"ACPI-safe"frequency3579545Hzquality850Timecounter"HPET"frequency100000000Hzquality900Timecounter"TSC"frequency3411154800Hzquality800Timecounterstickevery10.000msec# sysctl kern.timecounter.choicekern.timecounter.choice:TSC(800)HPET(900)ACPI-safe(850)i8254(0)dummy(-1000000)# sysctl kern.timecounter.hardware="ACPI-fast"kern.timecounter.hardware:HPET->ACPI-fast
Available clocks:
Thecommit 222222 (May2011) decreased ACPI-fast timecounter quality to 900 and increasedHPET timecounter quality to 950: “HPET on modern platforms usuallyhave better resolution and lower latency than ACPI timer”.
ReadTimecounters: Efficient and precise timekeeping in SMP kernels by Poul-Henning Kamp(2002) for the FreeBSD Project.
Reading a hardware clock has a cost. The following table comparesthe performance of different hardware clocks on Linux 3.3 with IntelCore i7-2600 at 3.40GHz (8 cores). Thebench_time.c programwas used to fill these tables.
| Function | TSC | ACPI PM | HPET |
|---|---|---|---|
| time() | 2 ns | 2 ns | 2 ns |
| CLOCK_REALTIME_COARSE | 10 ns | 10 ns | 10 ns |
| CLOCK_MONOTONIC_COARSE | 12 ns | 13 ns | 12 ns |
| CLOCK_THREAD_CPUTIME_ID | 134 ns | 135 ns | 135 ns |
| CLOCK_PROCESS_CPUTIME_ID | 127 ns | 129 ns | 129 ns |
| clock() | 146 ns | 146 ns | 143 ns |
| gettimeofday() | 23 ns | 726 ns | 637 ns |
| CLOCK_MONOTONIC_RAW | 31 ns | 716 ns | 607 ns |
| CLOCK_REALTIME | 27 ns | 707 ns | 629 ns |
| CLOCK_MONOTONIC | 27 ns | 723 ns | 635 ns |
FreeBSD 8.0 in kvm with hardware virtualization:
| Function | TSC | ACPI-Safe | HPET | i8254 |
|---|---|---|---|---|
| time() | 191 ns | 188 ns | 189 ns | 188 ns |
| CLOCK_SECOND | 187 ns | 184 ns | 187 ns | 183 ns |
| CLOCK_REALTIME_FAST | 189 ns | 180 ns | 187 ns | 190 ns |
| CLOCK_UPTIME_FAST | 191 ns | 185 ns | 186 ns | 196 ns |
| CLOCK_MONOTONIC_FAST | 188 ns | 187 ns | 188 ns | 189 ns |
| CLOCK_THREAD_CPUTIME_ID | 208 ns | 206 ns | 207 ns | 220 ns |
| CLOCK_VIRTUAL | 280 ns | 279 ns | 283 ns | 296 ns |
| CLOCK_PROF | 289 ns | 280 ns | 282 ns | 286 ns |
| clock() | 342 ns | 340 ns | 337 ns | 344 ns |
| CLOCK_UPTIME_PRECISE | 197 ns | 10380 ns | 4402 ns | 4097 ns |
| CLOCK_REALTIME | 196 ns | 10376 ns | 4337 ns | 4054 ns |
| CLOCK_MONOTONIC_PRECISE | 198 ns | 10493 ns | 4413 ns | 3958 ns |
| CLOCK_UPTIME | 197 ns | 10523 ns | 4458 ns | 4058 ns |
| gettimeofday() | 202 ns | 10524 ns | 4186 ns | 3962 ns |
| CLOCK_REALTIME_PRECISE | 197 ns | 10599 ns | 4394 ns | 4060 ns |
| CLOCK_MONOTONIC | 201 ns | 10766 ns | 4498 ns | 3943 ns |
Each function was called 100,000 times and CLOCK_MONOTONIC was used toget the time before and after. The benchmark was run 5 times, keepingthe minimum time.
NTP has different methods to adjust a clock:
adjtime()). Since the slew rate islimited to 0.5 millisecond per second, each second of adjustment requires anamortization interval of 2000 seconds. Thus, an adjustment of manyseconds can take hours or days to amortize.settimeofday())By default, the time is slewed if the offset is less than 128 ms, butstepped otherwise.
Slewing is generally desirable (i.e. we should use CLOCK_MONOTONIC,not CLOCK_MONOTONIC_RAW) if one wishes to measure “real” time (and nota time-like object like CPU cycles). This is because the clock on theother end of the NTP connection from you is probably better at keepingtime: hopefully that thirty-five thousand dollars of Cesiumtimekeeping goodness is doing something better than your PC’s $3quartz crystal, after all.
Get more detail in thedocumentation of the NTP daemon.
| Name | C Resolution | Adjusted | Include Sleep | Include Suspend |
|---|---|---|---|---|
| gethrtime() | 1 ns | No | Yes | Yes |
| CLOCK_HIGHRES | 1 ns | No | Yes | Yes |
| CLOCK_MONOTONIC | 1 ns | Slewed on Linux | Yes | No |
| CLOCK_MONOTONIC_COARSE | 1 ns | Slewed on Linux | Yes | No |
| CLOCK_MONOTONIC_RAW | 1 ns | No | Yes | No |
| CLOCK_BOOTTIME | 1 ns | ? | Yes | Yes |
| CLOCK_UPTIME | 1 ns | No | Yes | ? |
| mach_absolute_time() | 1 ns | No | Yes | No |
| QueryPerformanceCounter() | - | No | Yes | ? |
| GetTickCount[64]() | 1 ms | No | Yes | Yes |
| timeGetTime() | 1 ms | No | Yes | ? |
The “C Resolution” column is the resolution of the underlying Cstructure.
Examples of clock resolution on x86_64:
| Name | Operating system | OS Resolution | Python Resolution |
|---|---|---|---|
| QueryPerformanceCounter | Windows Seven | 10 ns | 10 ns |
| CLOCK_HIGHRES | SunOS 5.11 | 2 ns | 265 ns |
| CLOCK_MONOTONIC | Linux 3.0 | 1 ns | 322 ns |
| CLOCK_MONOTONIC_RAW | Linux 3.3 | 1 ns | 628 ns |
| CLOCK_BOOTTIME | Linux 3.3 | 1 ns | 628 ns |
| mach_absolute_time() | Mac OS 10.6 | 1 ns | 3 µs |
| CLOCK_MONOTONIC | FreeBSD 8.2 | 11 ns | 5 µs |
| CLOCK_MONOTONIC | OpenBSD 5.0 | 10 ms | 5 µs |
| CLOCK_UPTIME | FreeBSD 8.2 | 11 ns | 6 µs |
| CLOCK_MONOTONIC_COARSE | Linux 3.3 | 1 ms | 1 ms |
| CLOCK_MONOTONIC_COARSE | Linux 3.0 | 4 ms | 4 ms |
| GetTickCount64() | Windows Seven | 16 ms | 15 ms |
The “OS Resolution” is the resolution announced by the operatingsystem.The “Python Resolution” is the smallest difference between two callsto the time function computed in Python using theclock_resolution.pyprogram.
Mac OS X provides a monotonic clock: mach_absolute_time(). It isbased on absolute elapsed time since system boot. It is notadjusted and cannot be set.
mach_timebase_info() gives a fraction to convert the clock value to a number ofnanoseconds. See also theTechnical Q&A QA1398.
mach_absolute_time() stops during a sleep on a PowerPC CPU, but not onan Intel CPU:Different behaviour of mach_absolute_time() on i386/ppc.
CLOCK_MONOTONIC and CLOCK_MONOTONIC_RAW represent monotonic time sincesome unspecified starting point. They cannot be set. The resolutioncan be read usingclock_getres().
Documentation: refer to the manual page of your operating system.Examples:
CLOCK_MONOTONIC is available at least on the following operatingsystems:
The following operating systems don’t support CLOCK_MONOTONIC:
On Linux, NTP may adjust the CLOCK_MONOTONIC rate (slewed), but it cannotjump backward.
CLOCK_MONOTONIC_RAW is specific to Linux. It is similar toCLOCK_MONOTONIC, but provides access to a raw hardware-based time thatis not subject to NTP adjustments. CLOCK_MONOTONIC_RAW requires Linux2.6.28 or later.
Linux 2.6.39 and glibc 2.14 introduces a new clock: CLOCK_BOOTTIME.CLOCK_BOOTTIME is identical to CLOCK_MONOTONIC, except that it alsoincludes any time spent in suspend. Read alsoWaking systems fromsuspend (March, 2011).
CLOCK_MONOTONIC stops while the machine is suspended.
Linux provides also CLOCK_MONOTONIC_COARSE since Linux 2.6.32. It issimilar to CLOCK_MONOTONIC, less precise but faster.
clock_gettime() fails if the system does not support the specifiedclock, even if the standard C library supports it. For example,CLOCK_MONOTONIC_RAW requires a kernel version 2.6.28 or later.
High-resolution performance counter. It is monotonic.The frequency of the counter can be read using QueryPerformanceFrequency().The resolution is 1 / QueryPerformanceFrequency().
It has a much higher resolution, but has lower long term precisionthan GetTickCount() and timeGetTime() clocks. For example, it willdrift compared to the low precision clocks.
Documentation:
Hardware clocks used by QueryPerformanceCounter:
QueryPerformanceFrequency() should only be called once: the frequencywill not change while the system is running. It fails if theinstalled hardware does not support a high-resolution performancecounter.
QueryPerformanceCounter() cannot be adjusted:SetSystemTimeAdjustment()only adjusts the system time.
Bugs:
GetTickCount() and GetTickCount64() are monotonic, cannot fail and arenot adjusted by SetSystemTimeAdjustment(). MSDN documentation:GetTickCount(),GetTickCount64().The resolution can be read using GetSystemTimeAdjustment().
The elapsed time retrieved by GetTickCount() or GetTickCount64()includes time the system spends in sleep or hibernation.
GetTickCount64() was added to Windows Vista and Windows Server 2008.
It is possible to improve the precision using theundocumentedNtSetTimerResolution() function.There are applications using this undocumented function, example:TimerResolution.
WaitForSingleObject() uses the same timer as GetTickCount() with thesame precision.
The timeGetTime function retrieves the system time, in milliseconds.The system time is the time elapsed since Windows was started. ReadthetimeGetTime() documentation.
The return type of timeGetTime() is a 32-bit unsigned integer. AsGetTickCount(), timeGetTime() rolls over after 2^32 milliseconds (49.7days).
The elapsed time retrieved by timeGetTime() includes time the systemspends in sleep.
The default precision of the timeGetTime function can be fivemilliseconds or more, depending on the machine.
timeBeginPeriod() can be used to increase the precision oftimeGetTime() up to 1 millisecond, but it negatively affects powerconsumption. Calling timeBeginPeriod() also affects the granularityof some other timing calls, such as CreateWaitableTimer(),WaitForSingleObject() and Sleep().
Note
timeGetTime() and timeBeginPeriod() are part the Windows multimedialibrary and so require to link the program against winmm or todynamically load the library.
The Solaris OS has a CLOCK_HIGHRES timer that attempts to use anoptimal hardware source, and may give close to nanosecond resolution.CLOCK_HIGHRES is the nonadjustable, high-resolution clock. For timerscreated with a clockid_t value of CLOCK_HIGHRES, the system willattempt to use an optimal hardware source.
The resolution of CLOCK_HIGHRES can be read usingclock_getres().
The gethrtime() function returns the current high-resolution realtime. Time is expressed as nanoseconds since some arbitrary time inthe past; it is not correlated in any way to the time of day, and thusis not subject to resetting or drifting by way of adjtime() orsettimeofday(). The hires timer is ideally suited to performancemeasurement tasks, where cheap, accurate interval timing is required.
The linearity of gethrtime() is not preserved across a suspend-resumecycle (Bug 4272663).
Read thegethrtime() manual page of Solaris 11.
On Solaris, gethrtime() is the same as clock_gettime(CLOCK_MONOTONIC).
| Name | C Resolution | Include Sleep | Include Suspend |
|---|---|---|---|
| CLOCK_REALTIME | 1 ns | Yes | Yes |
| CLOCK_REALTIME_COARSE | 1 ns | Yes | Yes |
| GetSystemTimeAsFileTime | 100 ns | Yes | Yes |
| gettimeofday() | 1 µs | Yes | Yes |
| ftime() | 1 ms | Yes | Yes |
| time() | 1 sec | Yes | Yes |
The “C Resolution” column is the resolution of the underlying Cstructure.
Examples of clock resolution on x86_64:
| Name | Operating system | OS Resolution | Python Resolution |
|---|---|---|---|
| CLOCK_REALTIME | SunOS 5.11 | 10 ms | 238 ns |
| CLOCK_REALTIME | Linux 3.0 | 1 ns | 238 ns |
| gettimeofday() | Mac OS 10.6 | 1 µs | 4 µs |
| CLOCK_REALTIME | FreeBSD 8.2 | 11 ns | 6 µs |
| CLOCK_REALTIME | OpenBSD 5.0 | 10 ms | 5 µs |
| CLOCK_REALTIME_COARSE | Linux 3.3 | 1 ms | 1 ms |
| CLOCK_REALTIME_COARSE | Linux 3.0 | 4 ms | 4 ms |
| GetSystemTimeAsFileTime() | Windows Seven | 16 ms | 1 ms |
| ftime() | Windows Seven | - | 1 ms |
The “OS Resolution” is the resolution announced by the operatingsystem.The “Python Resolution” is the smallest difference between two callsto the time function computed in Python using theclock_resolution.pyprogram.
The system time can be read using GetSystemTimeAsFileTime(), ftime() andtime(). The resolution of the system time can be read usingGetSystemTimeAdjustment().
Read theGetSystemTimeAsFileTime() documentation.
The system time can be set using SetSystemTime().
gettimeofday(), ftime(), time() and clock_gettime(CLOCK_REALTIME) returnthe system time. The resolution of CLOCK_REALTIME can be read usingclock_getres().
The system time can be set using settimeofday() orclock_settime(CLOCK_REALTIME).
Linux provides also CLOCK_REALTIME_COARSE since Linux 2.6.32. It is similarto CLOCK_REALTIME, less precise but faster.
Alexander Shishkin proposed an API for Linux to be notified when the systemclock is changed:timerfd: add TFD_NOTIFY_CLOCK_SET to watch for clock changes (4th version of the API, March 2011). TheAPI is not accepted yet, but CLOCK_BOOTTIME provides a similar feature.
The process time cannot be set. It is not monotonic: the clocks stopwhile the process is idle.
| Name | C Resolution | Include Sleep | Include Suspend |
|---|---|---|---|
| GetProcessTimes() | 100 ns | No | No |
| CLOCK_PROCESS_CPUTIME_ID | 1 ns | No | No |
| getrusage(RUSAGE_SELF) | 1 µs | No | No |
| times() | - | No | No |
| clock() | - | Yes on Windows, No otherwise | No |
The “C Resolution” column is the resolution of the underlying Cstructure.
Examples of clock resolution on x86_64:
| Name | Operating system | OS Resolution | Python Resolution |
|---|---|---|---|
| CLOCK_PROCESS_CPUTIME_ID | Linux 3.3 | 1 ns | 1 ns |
| CLOCK_PROF | FreeBSD 8.2 | 10 ms | 1 µs |
| getrusage(RUSAGE_SELF) | FreeBSD 8.2 | - | 1 µs |
| getrusage(RUSAGE_SELF) | SunOS 5.11 | - | 1 µs |
| CLOCK_PROCESS_CPUTIME_ID | Linux 3.0 | 1 ns | 1 µs |
| getrusage(RUSAGE_SELF) | Mac OS 10.6 | - | 5 µs |
| clock() | Mac OS 10.6 | 1 µs | 5 µs |
| CLOCK_PROF | OpenBSD 5.0 | - | 5 µs |
| getrusage(RUSAGE_SELF) | Linux 3.0 | - | 4 ms |
| getrusage(RUSAGE_SELF) | OpenBSD 5.0 | - | 8 ms |
| clock() | FreeBSD 8.2 | 8 ms | 8 ms |
| clock() | Linux 3.0 | 1 µs | 10 ms |
| times() | Linux 3.0 | 10 ms | 10 ms |
| clock() | OpenBSD 5.0 | 10 ms | 10 ms |
| times() | OpenBSD 5.0 | 10 ms | 10 ms |
| times() | Mac OS 10.6 | 10 ms | 10 ms |
| clock() | SunOS 5.11 | 1 µs | 10 ms |
| times() | SunOS 5.11 | 1 µs | 10 ms |
| GetProcessTimes() | Windows Seven | 16 ms | 16 ms |
| clock() | Windows Seven | 1 ms | 1 ms |
The “OS Resolution” is the resolution announced by the operatingsystem.The “Python Resolution” is the smallest difference between two callsto the time function computed in Python using theclock_resolution.pyprogram.
Python source code includes a portable library to get the process time (CPUtime):Tools/pybench/systimes.py.
See also theQueryProcessCycleTime() function(sum of the cycle time of all threads) andclock_getcpuclockid().
The thread time cannot be set. It is not monotonic: the clocks stopwhile the thread is idle.
| Name | C Resolution | Include Sleep | Include Suspend |
|---|---|---|---|
| CLOCK_THREAD_CPUTIME_ID | 1 ns | Yes | Epoch changes |
| GetThreadTimes() | 100 ns | No | ? |
The “C Resolution” column is the resolution of the underlying Cstructure.
Examples of clock resolution on x86_64:
| Name | Operating system | OS Resolution | Python Resolution |
|---|---|---|---|
| CLOCK_THREAD_CPUTIME_ID | FreeBSD 8.2 | 1 µs | 1 µs |
| CLOCK_THREAD_CPUTIME_ID | Linux 3.3 | 1 ns | 649 ns |
| GetThreadTimes() | Windows Seven | 16 ms | 16 ms |
The “OS Resolution” is the resolution announced by the operatingsystem.The “Python Resolution” is the smallest difference between two callsto the time function computed in Python using theclock_resolution.pyprogram.
See also theQueryThreadCycleTime() function(cycle time for the specified thread) and pthread_getcpuclockid().
Gets the current unbiased interrupt time from the biased interrupttime and the current sleep bias amount. This time is not affected bypower management sleep transitions.
The elapsed time retrieved by the QueryUnbiasedInterruptTime functionincludes only time that the system spends in the working state.QueryUnbiasedInterruptTime() is not monotonic.
QueryUnbiasedInterruptTime() was introduced in Windows 7.
See alsoQueryIdleProcessorCycleTime() function(cycle time for the idle thread of each processor)
Suspend execution of the process for the given number of seconds.Sleep is not affected by system time updates. Sleep is paused duringsystem suspend. For example, if a process sleeps for 60 seconds andthe system is suspended for 30 seconds in the middle of the sleep, thesleep duration is 90 seconds in the real time.
Sleep can be interrupted by a signal: the function fails with EINTR.
| Name | C Resolution |
|---|---|
| nanosleep() | 1 ns |
| clock_nanosleep() | 1 ns |
| usleep() | 1 µs |
| delay() | 1 µs |
| sleep() | 1 sec |
Other functions:
| Name | C Resolution |
|---|---|
| sigtimedwait() | 1 ns |
| pthread_cond_timedwait() | 1 ns |
| sem_timedwait() | 1 ns |
| select() | 1 µs |
| epoll() | 1 ms |
| poll() | 1 ms |
| WaitForSingleObject() | 1 ms |
The “C Resolution” column is the resolution of the underlying Cstructure.
clock_nanosleep(clock_id, flags, nanoseconds, remaining):Linuxmanpage of clock_nanosleep().
If flags is TIMER_ABSTIME, then request is interpreted as an absolutetime as measured by the clock, clock_id. If request is less than orequal to the current value of the clock, then clock_nanosleep()returns immediately without suspending the calling thread.
POSIX.1 specifies that changing the value of the CLOCK_REALTIME clockvia clock_settime(2) shall have no effect on a thread that is blockedon a relative clock_nanosleep().
select(nfds, readfds, writefds, exceptfs, timeout).
Since Linux 2.6.28, select() uses high-resolution timers to handle thetimeout. A process has a “slack” attribute to configure the precisionof the timeout, the default slack is 50 microseconds. Before Linux2.6.28, timeouts for select() were handled by the main timingsubsystem at a jiffy-level resolution. Read alsoHigh- (but not toohigh-) resolution timeouts andTimer slack.
The ACPI power state “S3” is a system standby mode, also called“Suspend to RAM”. RAM remains powered.
On Windows, theWM_POWERBROADCAST message is sent to Windowsapplications to notify them of power-management events (ex: owner statushas changed).
For Mac OS X, readRegistering and unregistering for sleep and wakenotifications(Technical Q&A QA1340).
Related Python issues:
Libraries exposing monotonic clocks:
Time:
The PEP was accepted on 2012-04-28 by Guido van Rossum[1]. The PEPimplementation has since been committed to the repository.
This document has been placed in the public domain.
Source:https://github.com/python/peps/blob/main/peps/pep-0418.rst
Last modified:2025-02-01 08:55:40 GMT