« 衆院解散!感動した! | トップページ | タイマーAPIの処理時間を計測すると… »

2005年8月11日 (木)

タイマーAPIの精度は、どんなもん?

時間制御を行うには、
以下のAPIの
どれかを利用する。

多分…。

・GetTickCount
・timeGetTime
・timeGetSystemTime
・QueryPerformanceCounter

さて、これらの関数は、
どの程度の精度なんだろうか?

と言う事で調べてみた。

※「timeGetSystemTime」は、「timeGetSystemTime」の
ラッパーなので変換のオーバーヘッドが有るとヘルプには
書いてあるが、サンプルに使っていたので列挙!

※以下のソースは、拡張子を「cpp」に
しないとヘッダーでエラーが出るぞ!

無論!ボケも引っかかった!<エッヘン!

#pragma comment( lib, "WinMm.lib" )
//--------------------------------------
#include    <StdIo.h>
#include    <Windows.h>
//--------------------------------------
#define        COUNT_MAX    20
//--------------------------------------
void TimeFunction( void )
{
    DWORD        List[COUNT_MAX];
    DWORD        Time, Now, Count;
    MMTIME        mmTime;
    int            i;
    LARGE_INTEGER    PerformanceCount, Frequency;

    Time    = GetTickCount( );
    Count    = 0;
    do
    {
        if( Time != ( Now = GetTickCount( ) ) )
            Time    = List[Count++]    = Now;
    } while( Count < COUNT_MAX );
    printf( "\n■GetTickCount\n" );
    for( i = 0 ; i < COUNT_MAX - 1 ; i++ )
        printf( "%d : %2d\n", List[i], List[i + 1] - List[i] );

    Time    = timeGetTime( );
    Count    = 0;
    do
    {
        if( Time != ( Now = timeGetTime( ) ) )
            Time    = List[Count++]    = Now;
    } while( Count < COUNT_MAX );
    printf( "\n■timeGetTime\n" );
    for( i = 0 ; i < COUNT_MAX - 1 ; i++ )
        printf( "%d : %2d\n", List[i], List[i + 1] - List[i] );

    ZeroMemory( &mmTime, sizeof( mmTime ) );
    mmTime.wType    = TIME_TICKS;
    timeGetSystemTime( &mmTime, sizeof( mmTime ) );
    Count    = 0;
    do
    {
        timeGetSystemTime( &mmTime, sizeof( mmTime ) );
        if( Time != mmTime.u.ticks )
            Time    = List[Count++]    = mmTime.u.ticks;
    } while( Count < COUNT_MAX );
    printf( "\n■timeGetSystemTime\n" );
    for( i = 0 ; i < COUNT_MAX - 1 ; i++ )
        printf( "%d : %2d\n", List[i], List[i + 1] - List[i] );

    QueryPerformanceFrequency( &Frequency );
    Frequency.QuadPart    = Frequency.QuadPart / 1000;
    QueryPerformanceCounter( &PerformanceCount );
    Time    = ( DWORD )( PerformanceCount.QuadPart / Frequency.QuadPart );
    Count    = 0;
    do
    {
        QueryPerformanceCounter( &PerformanceCount );
        Now    = ( DWORD )( PerformanceCount.QuadPart / Frequency.QuadPart );
        if( Time != Now )
            Time    = List[Count++]    = Now;
    } while( Count < COUNT_MAX );
    printf( "\n■QueryPerformanceCounter\n" );
    for( i = 0 ; i < COUNT_MAX - 1 ; i++ )
        printf( "%d : %2d\n", List[i], List[i + 1] - List[i] );

    Time    = ( DWORD )PerformanceCount.QuadPart;
    Count    = 0;
    do
    {
        QueryPerformanceCounter( &PerformanceCount );
        Now    = ( DWORD )PerformanceCount.QuadPart & 0xFFFFF;
        if( Time != Now )
            Time    = List[Count++]    = Now;
    } while( Count < COUNT_MAX );
    printf( "\n■QueryPerformanceCounter(Special!:/%d)\n", ( DWORD )Frequency.QuadPart );
    for( i = 0 ; i < COUNT_MAX - 1 ; i++ )
        printf( "%d : %2d\n", List[i], List[i + 1] - List[i] );
}
//--------------------------------------
void main( void )
{
#if 0    // 禁断の魔法
    HANDLE            Handle;
    Handle = OpenProcess( PROCESS_SET_INFORMATION, TRUE, GetCurrentProcessId( ) );
    SetPriorityClass( Handle, REALTIME_PRIORITY_CLASS );
    CloseHandle( Handle );
#endif

    // 何にもしないで実行すると…
    TimeFunction( );

    // でも、こうすると…
    // 何かに影響があるかもかも…
    timeBeginPeriod( 1 );
    TimeFunction( );
    timeEndPeriod( 1 );
}

取り合えず動くから
良しとしとしよう…。

他の人の所だと
挙動が違うかも…。

でも、気にしないぞ!

試しに98と2Kでも
やってみる…。

すると驚くべき結果が!
こんなことが有って良いのか!
研究チームは、急遽ゲ○ツに
緊急取材を申し込んだ!

と、言うぐらいの
踊るべき事実が!

そう、踊るしかないぐらいの
衝撃が脳みそに刺さったのだ!

煽りは、置いといて…。

98だと…

 API          :精度(ミリセック)

・GetTickCount       :5
・timeGetTime        :1
・timeGetSystemTime     :1
・QueryPerformanceCounter  :1
・QueryPerformanceCounter(s):0.001

「timeBeginPeriod」を実行すると…

・GetTickCount       :1
・timeGetTime        :1
・timeGetSystemTime     :1
・QueryPerformanceCounter  :1
・QueryPerformanceCounter(s):0.001

2Kだと…

 API          :精度(ミリセック)

・GetTickCount       :10
・timeGetTime        :10
・timeGetSystemTime     :10
・QueryPerformanceCounter  :10
・QueryPerformanceCounter(s):0.001

「timeBeginPeriod」を実行すると…

・GetTickCount       :10
・timeGetTime        :1
・timeGetSystemTime     :1
・QueryPerformanceCounter  :1
・QueryPerformanceCounter(s):0.001

があぁぁぁん!

OSによって違うやん!

何処かのHPに
「timeBeginPeriod」を実行すると…
『「GetTickCount」の精度が上がる!』
とか…
『上がらんわい!嘘書くな!ボケ!』
とか…
書いてあったのは、
OSで挙動が違うからかぁ!

(納得)

同じ物なのに結果が違うのは…
勘弁して…>どっかの偉い人

とまあ、同じ物でも
OSによって挙動が異なるのを
プログラマーは、
血の涙を流しながら
何とかしている…

かもしれない…。

このようにして
第一歩から
けつまずくのであった!

所で…

出力結果中に
いきなり+10とかなるのは
そのタイミングで割り込みが
入ってしまっているため
なのだが…。

プリエンプティブマルチタスク
ちゅうのは、
基本的に割り込みの塊で
成り立っているので…

割り込み禁止は、
○○ちゃんに張り扇チョップ
食らうぐらいの大罪じゃ!

でも、割り込み禁止に近い
効果を組み込んであるので
「禁断の魔法」を有効に
してみよう。

出力のばらつきがなくなるぞ!

多分…。

ああ…。
なんか硬いぞ今回!

|

« 衆院解散!感動した! | トップページ | タイマーAPIの処理時間を計測すると… »

コメント

コメントを書く



(ウェブ上には掲載しません)




トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/108365/5401462

この記事へのトラックバック一覧です: タイマーAPIの精度は、どんなもん?:

« 衆院解散!感動した! | トップページ | タイマーAPIの処理時間を計測すると… »