Does Stopwatch.Gettimestamp ever roll over? Or roll back?
Asked Answered
S

4

6

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.

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.

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.

Then, Voila...an efficient and accurate microsecond DateTime.

But, we find that sometimes the Stopwatch.GetTimestamp() will return lower number.

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.

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.

EDIT: We're now calculating this value "per thread" and then "clamping it" to watch for jumps between cores to reset it.

Shred answered 24/1, 2012 at 0:54 Comment(4)
How can you have a "microsecond accurate sytem time" when UtcNow is not microsecond accurate? This number can only be used for precise timing of intervals.Enlistment
Sorry. Did you read my explanation? It only calls UtcNow once at the start of the application. From that point on it uses the system clock and computes the difference to get the current time.Shred
Stopwatch uses the high-resolution timers when it has access to them or they exist on the computer.Weapon
Acquiring high-resolution time stamps has a detailed description on the high performance counter timestamp, with illustrations and a FAQ.Menu
N
6

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

Neoplasm answered 24/1, 2012 at 1:0 Comment(5)
Thanks! This follows logic since it is a multi-threaded application. And your link gives a confirmation that a hardware and BIOS issue may cause this. I give you credit for the answer. Any suggestion on how to address this? We are simply keeping "lastClockTime" and comparing, it's it's less then we reset.Shred
@Wayne: Environment.TickCount apparently doesn't suffer from this issue, but it's less precise, and overflows in less than a month.Enlistment
We suffered from the overflow already. It was painful. And it's too far less precise for our needs. Thanks for offering, anyway.Shred
@Groo 1) Are you sure? 2) What is the precision? Is it 1ms? Or 15.6ms? (unless you increase timer resolution)Avow
@Eugen: no, I was wrong to comment that. Environment.TickCount has a resolution of ~16ms, so the only way to get better resolution is to use a QueryPerformanceCounter (or the Stopwatch which uses this under the hood, provided that high-res counters are available on that system).Enlistment
P
2

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

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

Perorate answered 24/1, 2012 at 1:1 Comment(0)
D
1

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() - 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. 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? ???? ???? ????, 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). See also this question's answers for more options (including 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...

Dispensary answered 19/12, 2013 at 16:58 Comment(0)
U
0

To specifically answer the high-level question "How often does Stopwatch.GetTimestamp() roll over?", Microsoft's answer is:

Not less than 100 years from the most recent system boot, and potentially longer based on the underlying hardware timer used. For most applications, rollover isn't a concern.

Ushas answered 30/11, 2020 at 21:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.