Recently I noticed that the author of libplctagresolved an issue with
timeBeginPeriod(). It's interesting to learn what happened and timer resolution.
The system timer resolution determines how frequently Windows performs two main actions:
- Update the timer tick count if a full tick has elapsed.
- Check whether a scheduled timer object has expired.
On Windows 7, the default timer resolution is 15.6 ms.
Let's say sleep for 50ms, it would have its time delay rounded to some multiple of the tick frequency.
View system clock resolution
To view your system clock resolution, you need the clockres tool by sysinternals.
Clockres v2.1 - Clock resolution display utility Copyright (C) 2016 Mark Russinovich Sysinternals Maximum timer interval: 15.625 ms Minimum timer interval: 0.500 ms Current timer interval: 0.997 ms
It said that it uses
As the doc said,
timeBeginPeriod() allows you requests a minimum resolution for periodic timers. And you must call this function before using timer services.
timeBeginPeriod() should be paired with
timeEndPeriod(), and they can be nested.
The effect of this function:
- Before Windows 10, version 2004
affects global windows setting
- From Windows 10, version 2004
for processes that call this function, windows use lowest value requested by any process; For processes which have not called this function, Windows does not guarantee a higher resolution than the default system resolution
- From Windows 11
if a window-owning process becomes fully occluded, minimized, or otherwise invisible or inaudible to the end user, Windows does not guarantee a higher resolution than the default system resolution
The doc also suggest to look at
SetProcessInformation() is available from Windows 8.
ProcessPowerThrottling enables throttling policies on a process, which can be used to balance out performance and power efficiency in cases where optimal performance is not required
when a process enabling PROCESS_POWER_THROTTLING_EXECUTION_SPEED the process will be classified as EcoQoS (before Windows 11, labeled as LowQoS).
if does not explicitly enable PROCESS_POWER_THROTTLING_EXECUTION_SPEED the system will use its own heuristics to automatically infer a Quality of Service level.
In Windows 11, if a window-owning process becomes fully occluded, minimized, or otherwise invisible or inaudible to the end user, Windows may automatically ignore the timer resolution request.
Another topic related to timer resolution is high-precision timing. Some referenced articles described how to get high-precision timing.
|GetSystemTimeAsFileTime||100ns||not better than GetTickCount||-|
|QueryPerformanceCounter||1 microsecond or better||-|
|GetSystemTimePreciseAsFileTime||the highest possible level of precision (<1us)||-||in Coordinated Universal Time (UTC) format|
Someone said QPC is not reliable, and must run on the same processor core with thread affinity. But microsoft claims that thread affinity is not need as this might affect your application's performance. Windows has evolved to improve this, see the next section.
QueryPerformanceCounter depends on hardware timer ( TSC or other motherboard timer) or platform timer. The precision depends on hardware timer resolution and access time, Precision = MAX [ Resolution, AccessTime].
|Version||QPC basis||Sync across cores|
|XP and 2000||TSC (some hardware systems' BIOS didn't indicate the hardware CPU characteristics correctly)||some multi-core or multi-processor systems used processors with TSCs that couldn't be synchronized across cores|
|Vista and Server 2008||used a platform counter (High Precision Event Timer (HPET)) or the ACPI Power Management Timer (PM timer)||shared between multiple processors|
|Windows 7 and Server 2008 R2||The majority of Windows 7 and Windows Server 2008 R2 computers have processors with constant-rate TSCs and use these counters as the basis for QPC||Windows use TSCs as the basis of QPC on single-clock domain systems where the operating system (or the hypervisor) is able to tightly synchronize the individual TSCs across all processors|
|Windows 8, Server 2012 R2||TSC||The TSC synchronization algorithm was significantly improved to better accommodate large systems with many processors|
Someone discussed using QueryPerformanceCounter and timeGetTime at the same time , so that if the result of QueryPerformanceCounter is not acceptable, use timeGetTime to fixup.
Another solution is using Windows kernel events, such as CreateEvent/SetEvent/WaitForSingleObject. WaitForSingleObject doesn't use a timer if you set infinite timeout. It depends on kernel scheduling inside Windows. Code
Windows has evolved to be more power-efficient. Use high time resolution only when it's necessary. High time resolution might hurt overall system performance and reduce battery run time.
If your application is performance critical, it should call
timeBeginPeriod() to request high timer resolution before using timer service; moreover, your application should not have any window in Windows 11.
QPC is typically the best method to use for high resolution timing.
- Timer Resolution
- timeBeginPeriod function (timeapi.h)
- SetProcessInformation function (processthreadsapi.h)
- Quality of Service
- High-Resolution Timers
- Implement a Continuously Updating, High-Resolution Time Provider for Windows
- Windows Timer Resolution: Megawatts Wasted
- usleep() for Windows (C/C++) + set timer resolution to lowest possible supported by system
- Precision is not the same as accuracy
- Timers, Timer Resolution, and Development of Efficient Code
- Better on the inside: under the hood of Windows 8
- Acquiring high-resolution time stamps
- Windows 系统时钟间隔