简体   繁体   English

Stopwatch.Gettimestamp 是否会翻转? 还是回滚?

[英]Does Stopwatch.Gettimestamp ever roll over? Or roll back?

In using Stopwatch.GetTimestamp() we find that if you record the return value and then continue calling it and comparing to the previous return value, it will eventually but unpredictably return a value less than the original.在使用 Stopwatch.GetTimestamp() 时,我们发现如果记录返回值,然后继续调用它并与之前的返回值进行比较,它最终会但不可预测地返回一个小于原始值的值。

Is this expected behavior?这是预期的行为吗?

The purpose of doing this in the production code is to have a microsecond accurate sytem time.在生产代码中这样做的目的是获得微秒精确的系统时间。

The technique involves calling DateTime.UtcNow and also calling Stopwatch.GetTimestamp() as originalUtcNow and originalTimestamp, respectively.该技术涉及分别调用 DateTime.UtcNow 和调用 Stopwatch.GetTimestamp() 作为 originalUtcNow 和 originalTimestamp。

From that point forward, the application simply calls Stopwatch.GetTimestamp() and using Stopwatch.Frequency it calculates the difference from the originalTimestamp variable and then adds that difference to the originalUtcNow.从那时起,应用程序只需调用 Stopwatch.GetTimestamp() 并使用 Stopwatch.Frequency 计算与 originalTimestamp 变量的差异,然后将该差异添加到 originalUtcNow。

Then, Voila...an efficient and accurate microsecond DateTime.然后,瞧……高效且准确的微秒 DateTime。

But, we find that sometimes the Stopwatch.GetTimestamp() will return lower number.但是,我们发现有时 Stopwatch.GetTimestamp() 会返回较低的数字。

It happens quite rarely.它很少发生。 Our thinking is to simply "reset" when that happens and continue.我们的想法是在发生这种情况时简单地“重置”并继续。

HOWEVER, it makes us doubt the accuracy of the Stopwatch.GetTimestamp() or suspect there is a bug in the .Net library.然而,它让我们怀疑 Stopwatch.GetTimestamp() 的准确性或怀疑 .Net 库中存在错误。

If you can shed some light on this, please do.如果你能对此有所了解,请这样做。

FYI, based on the current timestamp value, the frequence, and the long.MaxValue it appears unlikely that it will roll over during our lifetime unless it's a hardware issue.仅供参考,根据当前的时间戳值、频率和 long.MaxValue,除非是硬件问题,否则它在我们的生命周期内似乎不太可能翻转。

EDIT: We're now calculating this value "per thread" and then "clamping it" to watch for jumps between cores to reset it.编辑:我们现在正在“每个线程”计算这个值,然后“钳制它”以观察内核之间的跳转以重置它。

It's possible that you get the jump in time because your thread is jumping cores.您可能会及时获得跳跃,因为您的线程正在跳跃核心。 See the "note" on this page: http://msdn.microsoft.com/en-us/library/ebf7z0sw.aspx请参阅此页面上的“注释”: http : //msdn.microsoft.com/en-us/library/ebf7z0sw.aspx

The behavior of the Stopwatch class will vary from system to system depending on hardware support.秒表类的行为会因系统而异,具体取决于硬件支持。

See: http://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.ishighresolution.aspx请参阅: http : //msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.ishighresolution.aspx

Also, I believe the underlying equivalent win32 call ( QueryPerformanceCounter ) contains useful documentation: http://msdn.microsoft.com/en-us/library/windows/desktop/ms644904(v=vs.85).aspx另外,我相信底层等效的 win32 调用( QueryPerformanceCounter )包含有用的文档: http : //msdn.microsoft.com/en-us/library/windows/desktop/ms644904 ( v=vs.85 ) .aspx

I don't know exactly regarding about running backwards (which sounds like a small change backwards), but I have so far experienced three times that the value of Stopwatch.GetTimestamp() can change so enormously that it causes overflow exceptions in some further calculations of form about like this:我不完全知道关于向后运行(这听起来像是向后的一个变化),但到目前为止我已经经历了三倍,即 Stopwatch.GetTimestamp() 的值变化如此之大,以至于在一些进一步的计算中会导致溢出异常形式大约是这样的:
(Stopwatch.GetTimestamp() - ProgramStartStopwatchTimestamp) * n
where n is some large value, but small enough that if the Stopwatch weren't jumping around enormously, then the program could run years without having overflow exception.其中n是一个很大的值,但足够小,如果秒表没有大幅跳动,那么程序可以运行多年而不会出现溢出异常。 Note also that these exceptions occurred many hours after the program started, so the issue is not just that the Stopwatch ran backwards a little bit immediately after start.另请注意,这些异常发生在程序启动数小时后,因此问题不仅仅是秒表在启动后立即向后跑了一点。 It just jumped to totally different range, in whatever direction.它只是跳到了完全不同的范围,无论朝哪个方向。

Regarding Stopwatch rolling over, in one of the above cases it (not the difference, but Stopwatch) obtained value of something a la 0xFF4?关于秒表滚动,在上述一种情况下,它(不是差异,而是秒表)获得了 0xFF4 的值? ???? ??? ???? ??? ????, so it jumped to a range that was very close to rolling over. ????,所以它跳到了一个非常接近翻滚的范围。 After restarting the program multiple times, this new range was still consistently in effect.多次重新启动程序后,这个新范围仍然有效。 If that matters anymore considering the need to handle the jumps anyway...如果考虑到无论如何都需要处理跳跃,那再重要的话......

If it was additionally necessary to determine which core the timestamp was taken on then it probably helps to know executing core number.如果还需要确定时间戳记在哪个内核上,那么了解执行内核编号可能会有所帮助。 For this end, there are functions called GetCurrentProcessorNumber (available since Server 2003 and Vista) and GetCurrentProcessorNumberEx (available since Server 2008 R2 and Windows 7).为此,有名为GetCurrentProcessorNumber (自 Server 2003 和 Vista 起可用)和GetCurrentProcessorNumberEx (自 Server 2008 R2 和 Windows 7 起可用)的函数。 See also this question's answers for more options (including Windows XP).另请参阅此问题的答案以获取更多选项(包括 Windows XP)。
Note that core number can be changed by the scheduler any time.请注意,调度程序可以随时更改内核编号。 But when one reads the core number before reading Stopwatch timestamp, and after, and the core number remained same, then perhaps one can assume that the Stopwatch read was also performed on this core...但是当在读取秒表时间戳之前读取内核编号,并且之后,内核编号保持不变,那么也许可以假设秒表读取也是在这个内核上执行的......

To specifically answer the high-level question "How often does Stopwatch.GetTimestamp() roll over?", Microsoft's answer is:为了具体回答“ Stopwatch.GetTimestamp()多久翻转一次?”这个高级问题, 微软的回答是:

Not less than 100 years from the most recent system boot, and potentially longer based on the underlying hardware timer used.从最近一次系统启动算起不少于 100 年,根据所使用的底层硬件计时器,时间可能更长。 For most applications, rollover isn't a concern.对于大多数应用程序,翻转不是问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM