Recently I noticed that the author of libplctagresolved an issue with timeBeginPeriod(). It's interesting to learn what happened and timer resolution.

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 GetSystemTimeAdjustment() function.

timeBeginPeriod()

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().

SetProcessInformation()

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.

High-precision timing

Another topic related to timer resolution is high-precision timing. Some referenced articles described how to get high-precision timing.

Functionprecisionaccuracycomments
GetTickCount1ms10ms-55ms-
GetSystemTimeAsFileTime100nsnot better than GetTickCount-
QueryPerformanceCounter1 microsecond or better-
GetSystemTimePreciseAsFileTimethe 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

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].

VersionQPC basisSync across cores
XP and 2000TSC (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 2008used 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 R2The majority of Windows 7 and Windows Server 2008 R2 computers have processors with constant-rate TSCs and use these counters as the basis for QPCWindows 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 R2TSCThe TSC synchronization algorithm was significantly improved to better accommodate large systems with many processors

Other solutions

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

Summary

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.

References