.NET的时差

时间:2011-06-09 13:58:50

标签: .net datetime

我在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

这是不可思议的,但似乎需要任何毫秒的操作...... ANY TICK !!!

结果是

>>> 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)

我有什么问题吗?

在另一个版本中,我试着睡100个小时

Next i

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

Dim endTime = DateTime.Now

,但这里有惊喜,而不是100我凝胶总是93,7506或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,3757(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)

6 个答案:

答案 0 :(得分:4)

由于您不在循环外使用i,因此可能会优化掉。因此,您需要对DateTime.Now和减法进行两次调用。

此外,由于最近的CPU能够每秒发送数十亿次操作,因此只需几千次操作(从L1缓存和寄存器中获取的数据很少)将花费时间以*微秒为单位。

顺便说一句。如果你想做时间,Stopwatch类型是一种更好的方法。

答案 1 :(得分:2)

DateTime.Now没有高准确度。通常默认情况下大约为16ms,使用timeBeginPeriod可以减少到1ms。请注意,timeBeginPeriod具有系统范围的影响,可能会增加计算机的功耗。所以不应该轻易使用它。

想象一下,你在内核中有一个定时器,它每16ms运行一次某个函数。此函数更新DateTime.Now使用的当前时间。然后它决定在接下来的16ms内运行哪个线程 如果你打电话给sleep(100),你的线程将不会在接下来的约100ms内运行。但Windows并没有立即注意到100毫秒已经启动。它只会注意到下一个计时器事件。然后它决定再次运行你的线程。

这与Windows中的计时器粒度有关,并影响许多windows api函数,例如GetTickCountSleep,线程调度和计时器间隔。

要衡量效果,请使用基于QueryPerformanceCounterStopWatch类,并且不会遇到此问题。 (不幸的是,在某些多核计算机上,不同核心的时钟不同步,这是错误的。如果你的线程被安排在另一个核心上,当它以更大的间隔向后或向前跳跃时,不要感到惊讶)

答案 2 :(得分:2)

当您尝试衡量流程的耗用时间,尤其是短期运行流程时,您希望使用更好的工具System.Diagnostics.Stopwatch

DateTime.Now在测量过程持续时间方面不具备精确度和准确度的适当组合。

有关详情,建议您查看Eric Lippert's blog entry

答案 3 :(得分:2)

你必须使用秒表

正如其他人发布的那样

进一步..

你的循环:

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

将被删除

如果你有

,请使用JIT COMPILER

优化因此无法使用

答案 4 :(得分:1)

尝试使用秒表,但考虑到现代计算机以纳秒计算,我可以看到它花费不到一毫秒来增加整数2000次。

答案 5 :(得分:1)

是。使用DateTime.Now来测量精确的时间并不准确。请改用Stopwatch