DateTime.Now vs. GetSystemTime
-
Working with date and time is known to be a source of beautiful code...
System.DateTime.Now
gets the current system time, but you cannot set it. When you want to be able to set the system time, you can trySetSystemTime(ref SYSTEMTIME lpSystemTime)
ofkernel32.dll
; and there is also aGetSystemTime(ref SYSTEMTIME lpSystemTime)
function in that dll. When I played with these functions, I wrote some tests to make sure I got the conversion fromstruct SYSTEMTIME
toSystem.DateTime
and vice versa right.[Test]
public void GetSystemTime()
{
DateTime expected = System.DateTime.Now;
DateTime actual = SystemTime.GetSystemTime();
Assert.AreEqual(expected, actual);
}Well, that always failed: it takes a tick or two to do all the calculations. I had to update it to allow for some delay:
\[Test\] public void GetSystemTime() { DateTime expected = System.DateTime.Now; DateTime actual = SystemTime.GetSystemTime(); int delta = Math.Abs(Convert.ToInt32((actual - expected).Ticks)); int maxDuration = Convert.ToInt32(2 \* TimeSpan.TicksPerMillisecond); Assert.Less(delta, maxDuration); }
That's 2 Milliseconds for that simple code. But still it fails rather often:
Errors and Failures:
- Test Failure : XY.SystemTimeTests.GetSystemTime
Expected: less than 20000
But was: 147763
What does the computer do during those almost 15 ms? Is this a test for catching the computer asleep?
- Test Failure : XY.SystemTimeTests.GetSystemTime
-
Working with date and time is known to be a source of beautiful code...
System.DateTime.Now
gets the current system time, but you cannot set it. When you want to be able to set the system time, you can trySetSystemTime(ref SYSTEMTIME lpSystemTime)
ofkernel32.dll
; and there is also aGetSystemTime(ref SYSTEMTIME lpSystemTime)
function in that dll. When I played with these functions, I wrote some tests to make sure I got the conversion fromstruct SYSTEMTIME
toSystem.DateTime
and vice versa right.[Test]
public void GetSystemTime()
{
DateTime expected = System.DateTime.Now;
DateTime actual = SystemTime.GetSystemTime();
Assert.AreEqual(expected, actual);
}Well, that always failed: it takes a tick or two to do all the calculations. I had to update it to allow for some delay:
\[Test\] public void GetSystemTime() { DateTime expected = System.DateTime.Now; DateTime actual = SystemTime.GetSystemTime(); int delta = Math.Abs(Convert.ToInt32((actual - expected).Ticks)); int maxDuration = Convert.ToInt32(2 \* TimeSpan.TicksPerMillisecond); Assert.Less(delta, maxDuration); }
That's 2 Milliseconds for that simple code. But still it fails rather often:
Errors and Failures:
- Test Failure : XY.SystemTimeTests.GetSystemTime
Expected: less than 20000
But was: 147763
What does the computer do during those almost 15 ms? Is this a test for catching the computer asleep?
Well, if yours was absolutely the only thing thing that ran on the computer, you might expect this to work consistently. Sadly, in a multi-tasking environment, you cannot guarantee that it's going to be accurate.
- Test Failure : XY.SystemTimeTests.GetSystemTime
-
Well, if yours was absolutely the only thing thing that ran on the computer, you might expect this to work consistently. Sadly, in a multi-tasking environment, you cannot guarantee that it's going to be accurate.
Pete O'Hanlon wrote:
cannot guarantee that it's going to be accurate
But 15 milliseconds?!
-
Pete O'Hanlon wrote:
cannot guarantee that it's going to be accurate
But 15 milliseconds?!
Yup. You just need a couple of expensive processes running and that would easily be the case.
-
Working with date and time is known to be a source of beautiful code...
System.DateTime.Now
gets the current system time, but you cannot set it. When you want to be able to set the system time, you can trySetSystemTime(ref SYSTEMTIME lpSystemTime)
ofkernel32.dll
; and there is also aGetSystemTime(ref SYSTEMTIME lpSystemTime)
function in that dll. When I played with these functions, I wrote some tests to make sure I got the conversion fromstruct SYSTEMTIME
toSystem.DateTime
and vice versa right.[Test]
public void GetSystemTime()
{
DateTime expected = System.DateTime.Now;
DateTime actual = SystemTime.GetSystemTime();
Assert.AreEqual(expected, actual);
}Well, that always failed: it takes a tick or two to do all the calculations. I had to update it to allow for some delay:
\[Test\] public void GetSystemTime() { DateTime expected = System.DateTime.Now; DateTime actual = SystemTime.GetSystemTime(); int delta = Math.Abs(Convert.ToInt32((actual - expected).Ticks)); int maxDuration = Convert.ToInt32(2 \* TimeSpan.TicksPerMillisecond); Assert.Less(delta, maxDuration); }
That's 2 Milliseconds for that simple code. But still it fails rather often:
Errors and Failures:
- Test Failure : XY.SystemTimeTests.GetSystemTime
Expected: less than 20000
But was: 147763
What does the computer do during those almost 15 ms? Is this a test for catching the computer asleep?
Setting the system time is something you should almost never do. I hope you had a good reason for that. The system clock on a lot of machines only updates every ~15ms, so any time based test that expects a better resolution than that needs to use a dedicated high definition timer, e.g. QueryPerformanceCounter.
- Test Failure : XY.SystemTimeTests.GetSystemTime
-
Pete O'Hanlon wrote:
cannot guarantee that it's going to be accurate
But 15 milliseconds?!
There are a few thing you can test, first prevent switching of the CPU core by setting which core to use:
Process.GetCurrentProcess().ProcessorAffinity = new IntPtr(1);
Then make sure your process is having more exclusive access to that core:
Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;
Thread.CurrentThread.Priority = ThreadPriority.Highest;Just don't blame me if you're messing up your system. :)
Wrong is evil and must be defeated. - Jeff Ello[^]
-
There are a few thing you can test, first prevent switching of the CPU core by setting which core to use:
Process.GetCurrentProcess().ProcessorAffinity = new IntPtr(1);
Then make sure your process is having more exclusive access to that core:
Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;
Thread.CurrentThread.Priority = ThreadPriority.Highest;Just don't blame me if you're messing up your system. :)
Wrong is evil and must be defeated. - Jeff Ello[^]
Well, thanks for the hints... When I posted it here in the "Weird and Wonderful" - or the "Coding Horror" section as it was called previously - I chose this forum because the outcome of these simple lines of code is so "weird and wonderful". The little hints won't have much effect: the tests are running in Virtual Machines, there are several more VMs on that host, though almost all of them are "idle" - but you what Windows can do while the machine is idle...
-
Well, thanks for the hints... When I posted it here in the "Weird and Wonderful" - or the "Coding Horror" section as it was called previously - I chose this forum because the outcome of these simple lines of code is so "weird and wonderful". The little hints won't have much effect: the tests are running in Virtual Machines, there are several more VMs on that host, though almost all of them are "idle" - but you what Windows can do while the machine is idle...
A well, I don't have a clue how ProcessorAffinity is handled on a VM, but probably wrong. I just figured that your 15 ms was because of context switching and was simply curious.
Wrong is evil and must be defeated. - Jeff Ello[^]
-
Working with date and time is known to be a source of beautiful code...
System.DateTime.Now
gets the current system time, but you cannot set it. When you want to be able to set the system time, you can trySetSystemTime(ref SYSTEMTIME lpSystemTime)
ofkernel32.dll
; and there is also aGetSystemTime(ref SYSTEMTIME lpSystemTime)
function in that dll. When I played with these functions, I wrote some tests to make sure I got the conversion fromstruct SYSTEMTIME
toSystem.DateTime
and vice versa right.[Test]
public void GetSystemTime()
{
DateTime expected = System.DateTime.Now;
DateTime actual = SystemTime.GetSystemTime();
Assert.AreEqual(expected, actual);
}Well, that always failed: it takes a tick or two to do all the calculations. I had to update it to allow for some delay:
\[Test\] public void GetSystemTime() { DateTime expected = System.DateTime.Now; DateTime actual = SystemTime.GetSystemTime(); int delta = Math.Abs(Convert.ToInt32((actual - expected).Ticks)); int maxDuration = Convert.ToInt32(2 \* TimeSpan.TicksPerMillisecond); Assert.Less(delta, maxDuration); }
That's 2 Milliseconds for that simple code. But still it fails rather often:
Errors and Failures:
- Test Failure : XY.SystemTimeTests.GetSystemTime
Expected: less than 20000
But was: 147763
What does the computer do during those almost 15 ms? Is this a test for catching the computer asleep?
- Test Failure : XY.SystemTimeTests.GetSystemTime
-
Setting the system time is something you should almost never do. I hope you had a good reason for that. The system clock on a lot of machines only updates every ~15ms, so any time based test that expects a better resolution than that needs to use a dedicated high definition timer, e.g. QueryPerformanceCounter.
Exactly. That was my thinking too, resolution.
Regards, Rob Philpott.