Freigeben über


How to get high resolution timing info

We know that we can use GetTickCount to get timing info but the resolution of this API is limited to about 10 milliseconds, see MSDN:

https://msdn.microsoft.com/en-us/library/ms724408(VS.85).aspx

The resolution of the GetTickCount function is limited to the resolution of the system timer, which is typically in the range of 10 milliseconds to 16 milliseconds.

To get higher resolution timing info, two popular options are:

1. The multimedia timeGetTime function, you can use this API to get 1 millisecond resolution timing info:

        TIMECAPS timeCaps = {0};

       

        //use timeGetDevCaps to get the minimum and maximum

        //resolutions supported by the system

        timeGetDevCaps(&timeCaps, sizeof(timeCaps));

 

        printf("minimum device resolution is %d millisecond(s)\r\n",timeCaps.wPeriodMin);

        printf("maximum device resolution is %d millisecond(s)\r\n",timeCaps.wPeriodMax);

 

        //use timeBeginPeriod to adjust the timer resolution

        //you cannot set the resolution smaller than timeCaps.wPeriodMin

        MMRESULT result = timeBeginPeriod(timeCaps.wPeriodMin);

 

        if(result == TIMERR_NOERROR)

        {

               printf("time resolution set to: %d millisecond(s)\r\n",timeCaps.wPeriodMin);

        }

 

        DWORD ticks1 = timeGetTime();

 

        //doing some operation here

        //Sleep(5000);

 

        DWORD ticks2 = timeGetTime();

 

        printf("time elapsed: %d\r\n",ticks2 - ticks1);

 

        //use timeEndPeriod to clear the resolution adjusted by the previous call //timeBeginPeriod

        timeEndPeriod(timeCaps.wPeriodMin);

 

Internally, when you call timebeginPeriod to adjust the timer resolution, it calls into ntdll!NtSetTimerResolution which goes into kernel to manipulate the timer hardware. This resolution adjustment can affect the OS thread scheduling behavior and it can affect other applications, applications such as Windows Media Player uses these APIs and we don't see bad effect.

 

2. To get even higher resolution timing info, you can use QueryPerformanceFrequency and QueryPerformanceCounter:

 

         LARGE_INTEGER frequencyPerSec = {0};

        LARGE_INTEGER start = {0};

        LARGE_INTEGER end = {0};

 

        if(QueryPerformanceFrequency(&frequencyPerSec))

        {

               QueryPerformanceCounter(&start);

 

               //do something here

 

               QueryPerformanceCounter(&end);

 

              printf("elaplsed time: %I64d second(s)\r\n",

                        (end.QuadPart - start.QuadPart)/frequencyPerSec.QuadPart);

        }

 

These APIs can get higher resolution but their overhead is higher than timeGetTime also.

 

Another option is the rdtsc counter but the currently hardware may have problems for this counter. Currently, SQL Server 2008 uses timtGetTime like mechanism and QueryPerformanceFrequency/QueryPerformanceCounter to get timing info, it does not use rdtsc anymore:

 

Issues caused by rdtsc:

https://support.microsoft.com/kb/931279/en-us

 

https://blogs.msdn.com/b/psssql/archive/2008/12/16/how-it-works-sql-server-no-longer-uses-rdtsc-for-timings-in-sql-2008-and-sql-2005-service-pack-3-sp3.aspx

 

https://blogs.msdn.com/b/psssql/archive/2007/08/19/sql-server-2005-rdtsc-truths-and-myths-discussed.aspx