以下段落让我感到困惑:
来自文章:Acquiring high-resolution time stamps
当您需要分辨率为1微秒或更高的时间戳时 并且您不需要将时间戳同步到外部 时间参考,选择QueryPerformanceCounter, KeQueryPerformanceCounter,或KeQueryInterruptTimePrecise。当你 需要UTC同步时间戳,分辨率为1微秒 或者更好,选择GetSystemTimePreciseAsFileTime或 KeQuerySystemTimePrecise。
短语" 与外部时间参考同步" 这意味着什么? 我学到的是:
这个假设是否正确?
答案 0 :(得分:8)
各种Windows功能返回的“当前”时间并不总是以每分钟60秒的速度计数。
有时Windows 故意让时钟慢一点,或者更快一点:
这样做而不是让您的时钟突然 JUMP ,现在您的日志文件存在时间异常。
您可以使用GetSystemTimeAdjustment
查看Windows当前是否正在以更快或更慢或以名义价格计算时钟。例如,现在在我的电脑上:
但如果您的时钟距离正确的时间太远,Windows只会 BONK 您的时间到正确的时间。
所以返回的时间是:
| Function | Return type | Resolution | Timezone |
|--------------------------------|-------------------|------------|----------|
| GetLocalTime | SYSTEM_TIME (1ms) | ~10-15 ms | Local |
| GetSystemTime | SYSTEM_TIME (1ms) | ~10-15 ms | UTC |
| GetSystemTimeAsFileTime | FILE_TIME (0.1us) | ~10-15 ms | UTC |
| GetSystemTimeAsPreciseFileTime | FILE_TIME (0.1us) | 0.1 us | UTC |
随着时钟的跳跃,所有人都可以快速,慢速或跳跃。虽然 QueryPerformanceCounter 永远不会加速或减速。它总是以60s / min的速率计数。
| Function | Return type | Resolution | Timezone |
|--------------------------------|-------------------|------------|----------|
| GetLocalTime | SYSTEM_TIME (1ms) | ~10-15 ms | Local |
| GetSystemTime | SYSTEM_TIME (1ms) | ~10-15 ms | UTC |
| GetSystemTimeAsFileTime | FILE_TIME (0.1us) | ~10-15 ms | UTC |
| GetSystemTimeAsPreciseFileTime | FILE_TIME (0.1us) | 0.1 us | UTC |
| | | | |
| GetTickCount | Int32 (1ms) | ~10-15 ms | n/a |
| GetTickCount64 | Int64 (1ms) | ~10-15 ms | n/a |
| QueryPerformanceCounter | Int64 (ticks) | 0.1 us | n/a |
只要您的计算机时钟当前不在SystemTimeAdjustment
,经过的时间间隔就会测量:
将:
对于准确的时间测量,这些是您应该使用的两个功能。问题是,你关心哪个任务:
GetSystemTimeAsPreciseFileTime :“现在”的高分辨率测量
QueryPerformanceCounter :“经过时间”的高分辨率测量
应该注意SYSTEM_TIME
和GetLocalTime
返回的GetSystemTime
结构固有地限于毫秒精度。 GetSystemTime
无法为您提供亚毫秒级的分辨率,因为返回类型无法为您提供微秒:
struct SYSTEMTIME {
WORD wYear;
WORD wMonth;
WORD wDay;
WORD wHour;
WORD wMinute;
WORD wSecond;
WORD wMilliseconds; //<---- that's the limit
}
当您希望Windows将时间缩短为数年,数月,数天,数小时,分钟,秒时,您应该只使用SYSTEM_TIME
。另一方面,FILE_TIME
结构的最终精度为100ns(0.1 us)。
在我使用的语言中,我们使用DateTime
精度浮点Double
,其中:
这是COM,OLE,Delphi,VB,Excel,Lotus 123使用的日期时间方案;和SQL Server使用的日期时间方案类似(尽管它们使用的是1/1/1900而不是12/30/1899)
DateTime UtcNowPrecise()
{
const UInt64 OA_ZERO_TICKS = 94353120000000000; //12/30/1899 12:00am in ticks
const UInt64 TICKS_PER_DAY = 864000000000; //ticks per day
FILE_TIME ft;
GetSystemTimePreciseAsFileTime(out ft);
ULARGE_INTEGER dt; //needed to avoid alignment faults
dt.LowPart = ft.dwLowDateTime;
dt.HighPart = ft.dwHighDateTime;
return (dt.QuadPart - OA_ZERO_TICKS) / TICKS_PER_DAY;
}
DateTime NowPrecise()
{
const UInt64 OA_ZERO_TICKS = 94353120000000000; //12/30/1899 12:00am in ticks
const UInt64 TICKS_PER_DAY = 864000000000; //ticks per day
FILE_TIME ft;
GetSystemTimePreciseAsFileTime(out ft);
//Convert from UTC to local
FILE_TIME ftLocal;
if (!FileTimeToLocalFileTime(ft, ref ftLocal))
RaiseLastNativeError();
ULARGE_INTEGER dt; //needed to avoid alignment faults
dt.LowPart = ftLocal.dwLowDateTime;
dt.HighPart = ftLocal.dwHighDateTime;
return (dt.QuadPart - OA_ZERO_TICKS) / TICKS_PER_DAY;
}
答案 1 :(得分:0)
QueryPerformanceCounter()将告诉您自上次调用QueryPerformanceCounter()以来经过了多长时间。作为秒表非常有用,可以计算经过的时间。
GetSystemTimePreciseAsFileTime()会根据某些参考(例如系统时钟)略微精确地告诉您当前的日历/日期时间。例如,您可以使用它打印出2016年12月12日14:17:51&#34;。
因此,您的假设不正确。连接到GPS或网络时间源无论是否呼叫其中一个都不会改变。您的应用程序的需求将决定您应该调用哪个。
基本上你需要知道什么时间(GSTPAFT)或多少时间(QPC)?