2016-01-01 50 views
1

以下段落已經讓我感到困惑:QueryPerformanceCounter或GetSystemTimePreciseAsFileTime使用SNTP時?

從文章:Acquiring high-resolution time stamps

當你需要時間郵票1微秒或更好 的分辨率,所以您不需要時間戳進行同步到外部 時間參考,請選擇QueryPerformanceCounter, KeQueryPerformanceCounter或KeQueryInterruptTimePrecise。當您需要UTC同步的時間戳記,並且分辨率爲1微秒 或更高時,請選擇GetSystemTimePreciseAsFileTime或 KeQuerySystemTimePrecise。

這個短語是什麼「同步到外部時間基準」 確切指的是在這裏嗎? 我學到的是:

  1. 如果你的電腦沒有連接到GPS(通過串口或SNTP)使用QueryPerformanceCounter的
  2. 如果PC已連接,則使用GetSystemTimePreciseAsFileTime

這個假設是否正確?

回答

0

QueryPerformanceCounter()會非常精確地告訴您從上次調用QueryPerformanceCounter()以來經過了多少時間。作爲秒錶,計算經過時間非常有用。

GetSystemTimePreciseAsFileTime()會根據某些參考(如系統時鐘),稍微精確地告訴您當前的日曆/日期時間。例如,您可以使用它打印出「Dec 12 14:17:51 2016」。

因此,您的假設是不正確的。連接到全球定位系統或網絡時間源不會改變,無論你打電話或其他。您的應用程序的需求將決定您應該調用哪一個。基本上你需要知道什麼時間(GSTPAFT)或多少時間(QPC)?

2

「當前」由各種Windows功能返回的時間並不總是每次以60秒的速率計數。

有時的Windows 故意已經時鐘會稍微慢一點,還是有點快:

  • 如果您的PC時鐘是目前當前正確的時間背後:運行稍趕上
  • 如果您的PC時鐘是目前領先的當前corret時間:運行稍微慢讓正確的時間趕上這個

它這樣做,而不是讓你的時鐘突然JUMP,現在你的日誌文件有時間異常。

您可以使用GetSystemTimeAdjustment來看看Windows正在滴答作響目前您的時鐘快,或者名義利率。例如,現在我的電腦上:

  • 系統時間調整:殘疾人
  • 添加標稱15,6250毫秒每次更新

但是如果你的時鐘是太遠離正確的時間,Windows將只是BONK你的時間到了正確的時間。

時間可以跑,快,慢,前進,後退。 QueryPerformanceCounter的將不

因此,通過返回的時間:

| Function      | Return type  | Resolution | Timezone | 
|--------------------------------|-------------------|------------|----------| 
| GetLocalTime     | SYSTEM_TIME (1ms) | ~10-15 ms | Local | 
| GetSystemTime     | SYSTEM_TIME (1ms) | ~10-15 ms | UTC  | 
| GetSystemTimeAsFileTime  | FILE_TIME (0.1us) | ~10-15 ms | UTC  | 
| GetSystemTimeAsPreciseFileTime | FILE_TIME (0.1us) | 0.1 us  | UTC  | 

所有能跑得快,慢,或跳躍,爲您的時鐘跳動。雖然QueryPerformanceCounter永遠不會加快或放慢速度。它始終以60s/min的速率正好計數。

| Function      | Return type  | Resolution | Timezone | 
|--------------------------------|-------------------|------------|----------| 
| GetLocalTime     | SYSTEM_TIME (1ms) | ~10-15 ms | Local | 
| GetSystemTime     | SYSTEM_TIME (1ms) | ~10-15 ms | UTC  | 
| GetSystemTimeAsFileTime  | FILE_TIME (0.1us) | ~10-15 ms | UTC  | 
| GetSystemTimeAsPreciseFileTime | FILE_TIME (0.1us) | 0.1 us  | UTC  | 
|        |     |   |   | 
| GetTickCount     | Int32 (1ms)  | ~10-15 ms | n/a  | 
| GetTickCount64     | Int64 (1ms)  | ~10-15 ms | n/a  | 
| QueryPerformanceCounter  | Int64 (ticks)  | 0.1 us  | n/a  | 

那麼你關心

只要您的計算機的時鐘沒有目前正在進行SystemTimeAdjustment,經過間隔由測量:

  • GetSytemTimeAsPreciseFileTime
  • QueryPerformanceCounter的

將兩者:

  • 保持同步
  • 是彼此
  • 一微秒的十分之幾內具有爲100ns(0最終分辨率。1 us)

對於精確的時間測量,這些是您應該使用的兩個功能。你關心的任務,一個問題,:

  • GetSystemTimeAsPreciseFileTime:的 「現在」

    • 良好的日誌文件
    • 事件的時間戳高分辨率測量
    • 同步到UTC爲現在的跨機器協議
  • QueryPerformanceCounter的:的 「經過時間」

    • 利於過程

加成顫振基準標記
  • 測量持續時間高分辨率測量
  • 它應該是注意到由GetLocalTime返回的SYSTEM_TIME結構和GetSystemTime固有地限於毫秒精度。有沒有辦法讓GetSystemTime給你亞毫秒級的分辨率,完全是因爲返回類型沒有地方給你微秒:

    struct SYSTEMTIME { 
        WORD wYear; 
        WORD wMonth; 
        WORD wDay; 
        WORD wHour; 
        WORD wMinute; 
        WORD wSecond; 
        WORD wMilliseconds; //<---- that's the limit 
    } 
    

    當你想讓Windows下到打破時間,你應該只使用SYSTEM_TIME年,月,日,小時,分鐘,秒。另一方面,FILE_TIME結構的最終精度爲100ns(0.1 us)。

    精確時間函數

    在我使用的語言中,我們使用一個DateTime這是一個Double精度浮點,其中:

    • 整數部分表示自12/30/1899的天數
    • 分數部分表示一天24小時的一小部分

    這是所使用的日期時間方案通過COM,OLE,Delphi,VB,Excel,Lotus 123;並類似於SQL Server使用的日期時間方案(儘管它們使用1/1/1900而不是12/30/1899)

    DateTime UtcNowPrecise() 
    { 
        const UInt64 OA_ZERO_TICKS = 94353120000000000; //12/30/1899 12:00am in ticks 
        const UInt64 TICKS_PER_DAY = 864000000000;  //ticks per day 
    
        FILE_TIME ft; 
        GetSystemTimePreciseAsFileTime(out ft); 
    
        ULARGE_INTEGER dt; //needed to avoid alignment faults 
        dt.LowPart = ft.dwLowDateTime; 
        dt.HighPart = ft.dwHighDateTime; 
    
        return (dt.QuadPart - OA_ZERO_TICKS)/TICKS_PER_DAY; 
    } 
    
    DateTime NowPrecise() 
    { 
        const UInt64 OA_ZERO_TICKS = 94353120000000000; //12/30/1899 12:00am in ticks 
        const UInt64 TICKS_PER_DAY = 864000000000;  //ticks per day 
    
        FILE_TIME ft; 
        GetSystemTimePreciseAsFileTime(out ft); 
    
        //Convert from UTC to local 
        FILE_TIME ftLocal; 
        if (!FileTimeToLocalFileTime(ft, ref ftLocal)) 
         RaiseLastNativeError(); 
    
        ULARGE_INTEGER dt; //needed to avoid alignment faults 
        dt.LowPart = ftLocal.dwLowDateTime; 
        dt.HighPart = ftLocal.dwHighDateTime; 
    
        return (dt.QuadPart - OA_ZERO_TICKS)/TICKS_PER_DAY; 
    } 
    
    相關問題