我知道DateTime.Now(或DateTime.UtcNow)仅对系统计时器分辨率准确。有一个“未记录的”功能NtSetTimerResolution,但它是doesn't affect the current time。我已经在使用从DateTime.UtcNow的起始值和添加的Stopwatch计数器的混合解决方案,以实现微秒级的高精度。实际上,这非常有效,只是无法与系统上多个进程的时间值进行比较。

我现在想进一步校准我的基准时间。而且,如果不能提高DateTime.Now的精度,至少我想知道何时将其值更新为下一个值。我想到的是一个循环旋转很长时间,直到值更改为止,然后使用它并立即启动秒表。

像这样:(未经测试)

DateTime t0 = DateTime.UtcNow;
DateTime baseTime;
Stopwatch stopwatch = new Stopwatch();
while ((baseTime = DateTime.UtcNow) == t0);
stopwatch.Start();


我的假设是否正确,即等待值更改会给我提供所报告的值准确的那一刻?例如,如果我在所有报告通用日志的应用程序中都这样做,那么我应该获得比现在更具可比性的时间值。 (不过,我不想获得同步级别的准确性,只是获得更好的信息。)

我使用NtSetTimerResolution函数进行了一些测试,将其设置为最大分辨率,然后在循环中比较DateTime.UtcNow值。值似乎更精确/准确(此处无法区分)。但是我不确定在这里看到什么。程序开始时的当前分辨率每次都不同。不知道它是否会干扰其他流程,所以我不希望在生产代码中修改它。

最佳答案

NtSetTimerResolution()确实会更改系统计时器分辨率。从这个意义上讲,它与timeBeginPeriod / timeEndPeriod非常相似。但是NtSetTimerResolution可以在支持更高分辨率的硬件上启用低于1 ms的计时器分辨率。使用NtQueryTimerResolution调查限制。在XP以上运行Windows的大多数现代硬件都支持0.5 ms的分辨率。

这如何影响时间?好了,在Windows> XP上,系统时间(系统文件时间)或系统时间的更新间隔的粒度由系统心跳确定,这由计时器分辨率给出。

例子:

1)Windows 7,NtQueryTimerResolution返回的最大分辨率为5000(100 ns单位)。 NtSetTimerResolution允许将系统心跳设置为0.5 ms。系统时间(使用GetSystemTimeAsFileTime获取适当的分辨率来检测)将以0.5 ms的步长递增。因此,当前时间会受到影响,它的粒度会发生变化。

2)Windows> XP,timeBeginPeriod(1)将系统心跳更改为1 ms,但是时间间隔仍然很小。系统时间粒度不取决于Windows XP上的计时器分辨率。

...函数NtSetTimerResolution但不影响当前时间。

是的MSDN:调用timeBeginPeriod时请小心,因为频繁的调用会严重影响系统时钟,系统电源使用情况和调度程序。但是,MS无法在此处更新文档。 Windows 8.1计时方案已经消除了对系统时间的影响。顺便说一句:timeBeginPeriodtimeEndPeriod确实使用NtSetTimerResolution

提示:在系统时间过渡时调用NtSetTimerResolution,timeBeginPeriod和timeEndPeriod以减少影响。这可以通过在呼叫之前轮询系统时间转换来实现。

...添加了秒表计数器,可将精度降至微秒。不幸的是,Stopwatch没有考虑系统时间调整。您必须查询实际的系统时间调整(GetSystemTimeAdjustment ,并将通过此调用获得的增益应用于秒表频率。

简介:它是否更...精确/准确(在这里无法区分)。它具有更好的粒度,这意味着:精度和准确性。

注意:如此处所述,有人抱怨在高频心跳下运行系统。微软指出,功耗增加了多达25%。其他文章则提到了由于高频心跳而导致的许多兆瓦损失。与往常一样,您支付的越多,您得到的就越多。

09-06 04:55