Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GetLocalTime() API time resolution

Tags:

c

profile

I need to find out time taken by a function in my application. Application is a MS VIsual Studio 2005 solution, all C code.

I used thw windows API GetLocalTime(SYSTEMTIME *) to get the current system time before and after the function call which I want to measure time of. But this has shortcoming that it lowest resolution is only 1msec. Nothing below that. So I cannot get any time granularity in micro seconds.

I know that time() which gives the time elapsed since the epoch time, also has resolution of 1msec (No microseconds)

1.) Is there any other Windows API which gives time in microseconds which I can use to measure the time consumed by my function?

-AD

like image 648
goldenmean Avatar asked Sep 08 '08 13:09

goldenmean


2 Answers

There are some other possibilities.

QueryPerformanceCounter and QueryPerformanceFrequency

QueryPerformanceCounter will return a "performance counter" which is actually a CPU-managed 64-bit counter that increments from 0 starting with the computer power-on. The frequency of this counter is returned by the QueryPerformanceFrequency. To get the time reference in seconds, divide performance counter by performance frequency. In Delphi:

function QueryPerfCounterAsUS: int64;     
begin
  if QueryPerformanceCounter(Result) and
     QueryPerformanceFrequency(perfFreq)
  then
    Result := Round(Result / perfFreq * 1000000);
  else
    Result := 0;
end;

On multiprocessor platforms, QueryPerformanceCounter should return consistent results regardless of the CPU the thread is currently running on. There are occasional problems, though, usually caused by bugs in hardware chips or BIOSes. Usually, patches are provided by motherboard manufacturers. Two examples from the MSDN:

  • Programs that use the QueryPerformanceCounter function may perform poorly in Windows Server 2003 and in Windows XP
  • Performance counter value may unexpectedly leap forward

Another problem with QueryPerformanceCounter is that it is quite slow.

RDTSC instruction

If you can limit your code to one CPU (SetThreadAffinity), you can use RDTSC assembler instruction to query performance counter directly from the processor.

function CPUGetTick: int64;
asm
  dw 310Fh // rdtsc
end;

RDTSC result is incremented with same frequency as QueryPerformanceCounter. Divide it by QueryPerformanceFrequency to get time in seconds.

QueryPerformanceCounter is much slower thatn RDTSC because it must take into account multiple CPUs and CPUs with variable frequency. From Raymon Chen's blog:

(QueryPerformanceCounter) counts elapsed time. It has to, since its value is governed by the QueryPerformanceFrequency function, which returns a number specifying the number of units per second, and the frequency is spec'd as not changing while the system is running.

For CPUs that can run at variable speed, this means that the HAL cannot use an instruction like RDTSC, since that does not correlate with elapsed time.

timeGetTime

TimeGetTime belongs to the Win32 multimedia Win32 functions. It returns time in milliseconds with 1 ms resolution, at least on a modern hardware. It doesn't hurt if you run timeBeginPeriod(1) before you start measuring time and timeEndPeriod(1) when you're done.

GetLocalTime and GetSystemTime

Before Vista, both GetLocalTime and GetSystemTime return current time with millisecond precision, but they are not accurate to a millisecond. Their accuracy is typically in the range of 10 to 55 milliseconds. (Precision is not the same as accuracy) On Vista, GetLocalTime and GetSystemTime both work with 1 ms resolution.

like image 176
gabr Avatar answered Sep 23 '22 20:09

gabr


You can try to use clock() which will provide the number of "ticks" between two points. A "tick" is the smallest unit of time a processor can measure.

As a side note, you can't use clock() to determine the actual time - only the number of ticks between two points in your program.

like image 38
Kyle Cronin Avatar answered Sep 20 '22 20:09

Kyle Cronin