开发者

Time difference in .NET

I have the following code in a WinForm:

  Protected Overrides Sub OnMouseMove(ByVal e As System.Windows.Forms.MouseEventArgs)
    Dim startTime = DateTime.Now
    MyBase.OnMouseMove(e)

    Dim result As Double = 45654654
    For i = -1000 To 1000
      result = result / i
    Next i

    Dim endTime = DateTime.Now
    Console.WriteLine(">>> OnMouseMove time = {0}(ms) (start={1}:{3}; end={2}:{4})", (endTime - startTime).TotalMilliseconds, startTime.ToLongTimeString(), endTime.ToLongTimeString(), startTime.Ticks, endTime.Ticks)
  End Sub

This is incredible, but it seems that is take any millisecond that operations... ANY TICK!!!

the result is

>>> OnMouseMove time = 0(ms) (start=15:56:03:634432317630699089; end=15:56:03:634432317630699089)
>>> OnMouseMove time = 0(ms) (start=15:56:03:634432317630855340; end=15:56:03:634432317630855340)
>>> OnMouseMove time = 0(ms) (start=15:56:03:634432317630855340; end=15:56:03:634432317630855340)
>>> OnMouseMove time = 0(ms) (start=15:56:03:634432317631011591; end=15:56:03:634432317631011591)
>>> OnMouseMove time = 0(ms) (start=15:56:03:634432317631011591; end=15:56:03:634432317631011591)
>>> OnMouseMove time = 0(ms) (start=15:56:03:634432317631167842; end=15:56:03:634432317631167842)

Do I something wrong?

In an other varaint I try to sleep 100 ms

Next i

' sleep 100 ms '
System.Threading.Thread.Sleep(100)

Dim endTime = DateTime.Now

, but here surprise, innstead of 100 I gel always 93,7506 or 109,3757:

>>> OnMouseMove time = 93,7506(ms) (start=16:05:26:634432323267766416; end=16:05:26:634432323268703922)
>>> OnMouseMove time = 93,7506(ms) (start=16:05:26:634432323268860173; end=16:05:26:634432323269797679)
>>> OnMouseMove time = 109,3开发者_JS百科757(ms) (start=16:05:26:634432323269797679; end=16:05:27:634432323270891436)
>>> OnMouseMove time = 93,7506(ms) (start=16:05:27:634432323270891436; end=16:05:27:634432323271828942)
>>> OnMouseMove time = 93,7506(ms) (start=16:05:27:634432323271828942; end=16:05:27:634432323272766448)
>>> OnMouseMove time = 109,3757(ms) (start=16:05:31:634432323315891724; end=16:05:31:634432323316985481)


As you don't use i outside the loop it is probably optimised away. Thus you are timing two calls to DateTime.Now and a subtraction.

Additionally, with recent CPUs able to dispatch billions of operations per second, a mere few thousand operations (from L1 cache and registers as little data is involved) will take time measured in *micro*seconds.

BTW. If you want to do timings the Stopwatch type is a better approach.


DateTime.Now doesn't have a high accuracy. Typically it's around 16ms by default and get be reduced to 1ms using timeBeginPeriod. Note that timeBeginPeriod has system wide effects and can increase the power consumption of the computer. So it should not be used lightly.

Imagine you have a timer in the kernel which runs a certain function every 16ms. This function updates the current time used by DateTime.Now. Then it decides which thread to run for the next 16ms.
If you call sleep(100) your thread won't run for the next about 100ms. But windows doesn't instantly notice that the 100ms are up. It only notices on the next timer event. And then it decides to run your thread again.

This is related to the timer granularity in windows and affects many windows api functions such as GetTickCount, Sleep, thread scheduling and timer intervals.

To measure performance use the StopWatch class which is based on QueryPerformanceCounter and doesn't suffer from this problem. (Unfortunately it is buggy on some multicore machines where the clocks of different cores desync. Don't be surprised if it jumps backward or forward in time for larger intervals when your thread gets scheduled on another core)


When trying to measure the elapsed time of processes, particularly short-running processes, you want to utilize a better tool, System.Diagnostics.Stopwatch.

DateTime.Now is not going to have the appropriate combination of precision and accuracy for measuring process duration.

For more information, I encourage you to check Eric Lippert's blog entry.


you must use the stop watch

as others has posted

further..

your loop :

Dim result As Double = 45654654
For i = -1000 To 1000
  result = result / i
Next i

will be remove

by JIT COMPILER if you have

the optimisation so is not of use


Try using a stopwatch, but it I could see it taking less than a millisecond to increment an integer 2000 times, given that a modern computers think in terms of nanoseconds.


Yes. Using DateTime.Now to measure precise timing is not precise. Use Stopwatch instead.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜