以下段落让我困惑:
从文章:获取高分辨率时间戳
当您需要分辨率为1微秒或更高的时间戳并且您不需要将时间戳同步到外部时间参考时,请选择QueryPerformanceCounter,KeQueryPerformanceCounter或KeQueryInterruptTimePrecise.如果需要分辨率为1微秒或更高的UTC同步时间戳,请选择GetSystemTimePreciseAsFileTime或KeQuerySystemTimePrecise.
短语" 要与外部时间参考同步 "在这里意味着什么?我学到的是这个:
如果您的PC未连接到GPS(通过串行端口或SNTP),请使用QueryPerformanceCounter.
如果PC已连接,则使用GetSystemTimePreciseAsFileTime.
这个假设是否正确?
各种Windows功能返回的"当前"时间并不总是以每分钟60秒的速度计数.
有时Windows会故意让时钟慢一点,或者更快一点:
如果您的PC时钟当前落后于当前正确的时间:运行稍快一点赶上
如果您的PC时钟当前超过当前的校正时间:运行稍慢以让正确的时间赶上这一点
它这样做而不是让你的时钟突然JUMP,现在你的日志文件有暂时的异常.
您可以使用GetSystemTimeAdjustment
以查看Windows当前是以更快还是更慢的速度或以标称速率滴答您的时钟.例如,现在在我的电脑上:
系统时间调整:已禁用
每次更新增加标称值15,6250 ms
但是,如果你的时钟是太远离正确的时间,Windows将只是BONK你的时间,以正确的时间.
时间可以快速,慢速,向前跳跃,向后跳跃.QueryPerformanceCounter不会所以回归的时间是:
| 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
,经过的时间间隔通过以下方式测量:
GetSytemTimeAsPreciseFileTime
QueryPerformanceCounter的
将两者:
同步
在彼此的十分之几微秒内
最终分辨率为100ns(0.1 us)
对于准确的时间测量,这些是您应该使用的两个功能.问题是,你关心哪个任务:
GetSystemTimeAsPreciseFileTime:"现在"的高分辨率测量
适合日志文件
事件的时间戳
同步到UTC以获得"现在"的跨机器协议
QueryPerformanceCounter:"经过时间"的高分辨率测量
适合做台标
测量过程的持续时间
奖金Chatter
应当指出的是,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 }
您应该只SYSTEM_TIME
在希望Windows将时间缩短为数年,数月,数天,数小时,分钟,秒时使用.FILE_TIME
另一方面,该结构的最终精度为100ns(0.1 us).
在我使用的语言中,我们使用的DateTime
是Double
精度浮点数,其中:
整数部分表示自18/30/1899以来的天数
小数部分代表24小时工作日的一小部分
这是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; }