Stopwatch.ElapsedTicks的祕密

這次的程式魔人賽,在先前的範例中,用的是Stopwatch.ElapsedTicks做為計數單位。

發現一件好玩的事,我在自己的機器上用DummyPlayer來跑,每一次就算胡亂猜也要近1,000 Ticks。但我接到一組參考數字,DummyPlayer在Q9300上跑,每次大約10-20 Ticks!!

不會吧?? Q6600輸Q9300這麼多?? 接著,更扯的事出現了,另一組DummyPlayer在PentiumD 920上的測試數據,Ticks數也不到100,我的Q6600是中了詛咒嗎?

這讓我想起之前研究過Thread.Sleep精確度的問題,大概有個結論是,計時的精確度與主機板、BIOS、OS有關係。再一查證,Q9300與PentiumD 930用的都是Asus的主機板,加上用Stopwatch計算int i=1做一次跟做10次的ElapsedTicks差不多,大概就有了初步推論(後來證實是錯的),這是不同硬體下造成的精準度的差異,而Asus的主機測量的Tick精確度較高。

會做出以上的推論,是基於一個錯誤的假設: 一個Tick代表的時間長度放諸四海皆同(誤)。

Google到Stopwatch.Frequency的MSDN文件,終於真相大白: 一個Ticks代表的時間長度會隨著硬體不同而有差異。例如我們可以用以下的Code在不同機器上做比較。

using System;
using System.IO;
using System.Threading;
using System.Diagnostics;
 
public class CSharpLab
{
    public static void Test()
    {
        Stopwatch sw = new Stopwatch();
        sw.Start();
        int k = 0;
        sw.Stop();
        Console.WriteLine("Ticks={0:N0}", sw.ElapsedTicks);
        Console.WriteLine("Freq={0:N0}", Stopwatch.Frequency);
        decimal ns = 1000000000M / Stopwatch.Frequency;
        Console.WriteLine("1 Tick = {0:N4}ns", ns);
    }
}
 

測試結果,我的Q6600工作機Freq=2,400,730,000(太約就是2.4Ghz,等於Q6600的CPU內頻),而Asus主板上測得Freq=3,579,545,相差了670倍,也就是說,在我的旗艦上,1 Tick = 0.4165 ns,Asus主板則為 1 Tick = 279.3651ns。如果換算回ms,則1200 Ticks與20 Ticks的時間長度就不會相去太遠。

經過了這番探索,得到了新結論:

  1. 不同硬體上,每個Tick代表的時間長度可能不同
  2. 每秒Tick數的極限應該就是CPU的內頻大小 (不過可測出的最小時間間隔也要好幾百Ticks)
  3. 測試結果比對時,Asus主板的Tick數少,反而是因為其Tick精確度較低所致(跟原來猜想的剛好相反)
歡迎推文分享:
Published 15 August 2008 06:49 AM 由 Jeffrey
Filed under: ,
Views: 12,404



意見

沒有意見

你的看法呢?

(必要的) 
(必要的) 
(選擇性的)
(必要的) 
(提醒: 因快取機制,您的留言幾分鐘後才會顯示在網站,請耐心稍候)

5 + 3 =

搜尋

Go

<August 2008>
SunMonTueWedThuFriSat
272829303112
3456789
10111213141516
17181920212223
24252627282930
31123456
 
RSS
創用 CC 授權條款
【廣告】
twMVC

Tags 分類檢視
關於作者

一個醉心技術又酷愛分享的Coding魔人,十年的IT職場生涯,寫過系統、管過專案, 也帶過團隊,最後還是無怨無悔地選擇了技術鑽研這條路,近年來則以做一個"有為的中年人"自許。

文章典藏
其他功能

這個部落格


Syndication