当前位置:  开发笔记 > 后端 > 正文

QueryPerformanceCounter或GetSystemTimePreciseAsFileTime使用SNTP时?

如何解决《QueryPerformanceCounter或GetSystemTimePreciseAsFileTime使用SNTP时?》经验,为你挑选了1个好方法。

以下段落让我困惑:

从文章:获取高分辨率时间戳

当您需要分辨率为1微秒或更高的时间戳并且您不需要将时间戳同步到外部时间参考时,请选择QueryPerformanceCounter,KeQueryPerformanceCounter或KeQueryInterruptTimePrecise.如果需要分辨率为1微秒或更高的UTC同步时间戳,请选择GetSystemTimePreciseAsFileTime或KeQuerySystemTimePrecise.

短语" 要与外部时间参考同步 "在这里意味着什么?我学到的是这个:

    如果您的PC未连接到GPS(通过串行端口或SNTP),请使用QueryPerformanceCounter.

    如果PC已连接,则使用GetSystemTimePreciseAsFileTime.

这个假设是否正确?



1> Ian Boyd..:

各种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结构返回的GetLocalTimeGetSystemTime固有限制为精确到毫秒.没有办法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).

精确的时间功能

在我使用的语言中,我们使用的DateTimeDouble精度浮点数,其中:

整数部分表示自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;
}

推荐阅读
我我檬檬我我186
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有