Windows Time
Windows time is the number of milliseconds elapsed since the system was last started. This format exists primarily for backward compatibility with 16-bit Windows. To ensure that applications designed for 16-bit Windows continue to run successfully, the GetTickCount function returns the current Windows time.
- system timer
- multimedia timer
- high-resolution timer
1. system timer
// Retrieves the number of milliseconds that have elapsed since the system was started, up to 49.7 days.
DWORD GetTickCount();
// Retrieves the number of milliseconds that have elapsed since the system was started.
ULONGLONG GetTickCount64();
Remarks
GetTickCount
and GetTickCount64
are limited to the resolution of the system timer, which is approximately 10 milliseconds to 16 milliseconds. The elapsed time retrieved by GetTickCount
or GetTickCount64
includes time the system spends in sleep or hibernation.
For GetTickCount()
, the elapsed time is stored as a DWORD
value. Therefore, the time will wrap around to zero if the system is run continuously for 49.7 days. To avoid this problem, use the GetTickCount64
function. Otherwise, check for an overflow condition when comparing times.
If you need a higher resolution timer, use a multimedia timer or a high-resolution timer.
2. multimedia timer
The multimedia timer services allow an application to schedule periodic timer events — that is, the application can request and receive timer messages at application-specified intervals.
Multimedia timer services allow applications to schedule timer events with the greatest resolution (or accuracy) possible for the hardware platform. These multimedia timer services allow you to schedule timer events at a higher resolution than other timer services.
These timer services are useful for applications that demand high-resolution timing. For example, a MIDI sequencer requires a high-resolution timer because it must maintain the pace of MIDI events within a resolution of 1 millisecond.
/* Retrieves the system time, in milliseconds.
The system time is the time elapsed since Windows was started. */
DWORD timeGetTime();
使用 timeGetTime
时必须先包含多媒体库 Winmm.lib,可以在代码中添加:
#pragma comment(lib, "winmm")
或
#pragma comment(lib, "winmm.lib")
Remarks
The only difference between this function and the timeGetSystemTime
function is that timeGetSystemTime
uses the MMTIME
structure to return the system time. The timeGetTime
function has less overhead than timeGetSystemTime.
Note that the value returned by the timeGetTime
function is a DWORD
value. The return value wraps around to 0 every 2^32 milliseconds, which is about 49.71 days. This can cause problems in code that directly uses the timeGetTime
return value in computations, particularly where the value is used to control code execution. You should always use the difference between two timeGetTime
return values in computations.
The default precision of the timeGetTime
function can be five milliseconds or more, depending on the machine. You can use the timeBeginPeriod
and timeEndPeriod
functions to increase the precision of timeGetTime
. If you do so, the minimum difference between successive values returned by timeGetTime
can be as large as the minimum period value set using timeBeginPeriod
and timeEndPeriod
.
Use the QueryPerformanceCounter
and QueryPerformanceFrequency
functions to measure short time intervals at a high resolution.
3. high-resolution timer
A counter is a general term used in programming to refer to an incrementing variable. Some systems include a high-resolution performance counter that provides high-resolution elapsed times.
If a high-resolution performance counter exists on the system, you can use the QueryPerformanceFrequency
function to express the frequency, in counts per second. The value of the count is processor dependent. On some processors, for example, the count might be the cycle rate of the processor clock.
The QueryPerformanceCounter
function retrieves the current value of the high-resolution performance counter. By calling this function at the beginning and end of a section of code, an application essentially uses the counter as a high-resolution timer. For example, suppose that QueryPerformanceFrequency
indicates that the frequency of the high-resolution performance counter is 50,000 counts per second. If the application calls QueryPerformanceCounter
immediately before and immediately after the section of code to be timed, the counter values might be 1500 counts and 3500 counts, respectively. These values would indicate that .04 seconds (2000 counts) elapsed while the code executed.
/* Retrieves the frequency of the performance counter. The frequency of the
performance counter is fixed at system boot and is consistent across all processors.
Therefore, the frequency need only be queried upon application initialization,
and the result can be cached. */
BOOL QueryPerformanceFrequency(
LARGE_INTEGER *lpFrequency
);
Parameters
lpFrequency
A pointer to a variable that receives the current performance-counter frequency, in counts per second. If the installed hardware doesn’t support a high-resolution performance counter, this parameter can be zero (this will not occur on systems that run Windows XP or later).
Return value
If the installed hardware supports a high-resolution performance counter, the return value is nonzero.
If the function fails, the return value is zero. To get extended error information, call GetLastError. On systems that run Windows XP or later, the function will always succeed and will thus never return zero.
/* Retrieves the current value of the performance counter, which is a high
resolution (<1us) time stamp that can be used for time-interval measurements. */
BOOL QueryPerformanceCounter(
LARGE_INTEGER *lpPerformanceCount
);
Parameters
lpPerformanceCount
A pointer to a variable that receives the current performance-counter value, in counts.
Return value
If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero. To get extended error information, call GetLastError. On systems that run Windows XP or later, the function will always succeed and will thus never return zero.
Example:
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
inline DWORD GetTick_ms()
{
#if defined(_MSC_VER)
LARGE_INTEGER tFrequency = { 0 };
LARGE_INTEGER tPerformanceCount = { 0 };
// 获取晶振频率
QueryPerformanceFrequency(&tFrequency);
// 获取晶振数
QueryPerformanceCounter(&tPerformanceCount);
// 计算获得时间片
return (DWORD)((tPerformanceCount.QuadPart * 1000 / tFrequency.QuadPart) & 0x00000000FFFFFFFF);
#else
struct timespec tTimeTick = {0};
clock_gettime(CLOCK_MONOTONIC, &tTimeTick);
return (DWORD)((tTimeTick.tv_sec * 1000) + (tTimeTick.tv_nsec / 1000000));
#endif
}
inline DWORD GetTick_us()
{
LARGE_INTEGER tFrequency = { 0 };
LARGE_INTEGER tPerformanceCount = { 0 };
// 获取晶振频率
QueryPerformanceFrequency(&tFrequency);
// 获取晶振数
QueryPerformanceCounter(&tPerformanceCount);
// 计算获得时间片
return (DWORD)((tPerformanceCount.QuadPart * 1000 * 1000 / tFrequency.QuadPart) & 0x00000000FFFFFFFF);
}
inline DWORD GetTick_ns()
{
LARGE_INTEGER tFrequency = { 0 };
LARGE_INTEGER tPerformanceCount = { 0 };
// 获取晶振频率
QueryPerformanceFrequency(&tFrequency);
// 获取晶振数
QueryPerformanceCounter(&tPerformanceCount);
// 计算获得时间片
return (DWORD)((tPerformanceCount.QuadPart * 1000 * 1000 * 1000 / tFrequency.QuadPart) & 0x00000000FFFFFFFF);
}
int main()
{
// 获取晶振频率
LARGE_INTEGER tFrequency = { 0 };
QueryPerformanceFrequency(&tFrequency);
printf("晶振频率 : %ld Hz\n\n", tFrequency.QuadPart);
// test ms
int nIndex = 0;
while (nIndex++ < 3)
{
DWORD dwTime1 = GetTick_ms();
Sleep(1000); //ms
DWORD dwTime2 = GetTick_ms();
printf("time interval : %d ms\n\n", dwTime2 - dwTime1);
}
// test us
nIndex = 0;
while (nIndex++ < 3)
{
DWORD dwTime1 = GetTick_us();
Sleep(1000); //ms
DWORD dwTime2 = GetTick_us();
printf("time interval : %d us\n\n", dwTime2 - dwTime1);
}
// test ns
nIndex = 0;
while (nIndex++ < 3)
{
DWORD dwTime1 = GetTick_ns();
Sleep(1000); //ms
DWORD dwTime2 = GetTick_ns();
printf("time interval : %d ns\n\n", dwTime2 - dwTime1);
}
system("pause");
return 0;
}
output: