2012-03-23 57 views
0

我寫了一些代碼,使用緊密循環來監控Stopwatch的輸出。該循環跟蹤自上次迭代以來已經過去的滴答數。我觀察到每秒20次500微秒的跳躍,而大多數其他迭代需要1秒鐘。秒錶似乎在緊密循環的迭代之間跳躍500μs

有人可以解釋爲什麼我看到這些跳躍?

我已經試過:

  1. 設置處理器親和力(無效果)
  2. 更改線程的優先級(最高/ AboveNormal使事情變得更糟)
  3. 運行調試
  4. 發佈建立與外優化

我的代碼如下:

 Stopwatch sw = new Stopwatch(); 
     int crossThresholdCount = 0; 
     long lastElapsedTicks = 0; 
     long lastPrintTicks = 0; 
     Console.WriteLine("IsHighResolution: " + Stopwatch.IsHighResolution); 
     Console.WriteLine("Frequency: " + Stopwatch.Frequency); 

     sw.Start(); 

     long thresholdTicks = 5000; // 10000 ticks per ms 
     while (true) 
     { 
      long tempElapsed = sw.ElapsedTicks; 
      long sincePrev = tempElapsed - lastElapsedTicks; 
      lastElapsedTicks = tempElapsed; 

      if (sincePrev > thresholdTicks) 
       crossThresholdCount++; 

      // print output 
      if (crossThresholdCount > 0 && tempElapsed - lastPrintTicks > TimeSpan.TicksPerSecond) 
      { 
       lastPrintTicks = tempElapsed; 
       Console.WriteLine("crossed " + crossThresholdCount + " times"); 
       crossThresholdCount = 0; 
      } 
     } 
+0

您是否曾嘗試在程序中運行兩次測試代碼以消除JIT效應? – 2012-03-23 21:51:43

+0

如果用存儲器替換console.writeline代碼以列出變量,然後在循環完成後立即打印所有時序,會發生什麼情況? – rism 2012-03-23 21:59:58

回答

5

您很可能會看到先發制人的任務切換。這是當操作系統暫停您的程序,並開始執行其他程序。這是自Windows 95以來的事情(Win 3.1及更早版本具有協作式多任務處理功能,因此您可以將CPU保持爲您想要的時間)。

順便提一句,有一個更好的方法來準確計算執行時間:QueryThreadCycleTime,僅在您的代碼正在執行時才計算CPU週期,因此不包括此類暫停。

+0

Win 3.1實際上對DOS應用程序進行搶先式多任務處理,對Windows應用程序進行協同式多任務處理。 – 2012-03-23 21:57:17

+0

QueryThreadCycleTime爲+1 – rism 2012-03-23 22:01:32

+0

不會將線程優先級設置爲Highest reduce/prevent搶佔?當我將它設置爲最高時,跳躍次數從每秒20次到每秒200次 – 2012-03-23 22:17:17

3

您的測試沒有意義......您的過程不是您的機器上唯一運行的過程。系統依次爲每個線程提供處理器時間,因此有些時候你的循環根本沒有運行,這就解釋了「跳躍」。