高分解能パフォーマンスカウンタを使用した処理時間の測定

パフォーマンスチェック時に高精度なタイマーを使用したい場合があります。

Windowsには、QueryPerformanceCounter関数と言う高精度(=高分解)なパフォーマンスカウンタAPIを持っています。
コレを利用する事で短い処理時間でも高精度での測定が可能となります。

QueryPerformanceCounter関数は実際のところ、CPUクロックをカウントしていると思われるため実行するマシンの性能により精度が変化します。
ちなみに精度を取得するのがQueryPerformanceFrequency関数で、通常はミリ秒より精度が良いはずです
また、あまりにもCPUが古いとサポートされていないため実行できません。
恐らく、Pentium以降ならサポートしてるかと・・・。

サンプル(32bit) ダウンロード

'高分解能パフォーマンスカウンタ用API
Private Declare Function QueryPerformanceCounter Lib "kernel32" (lpPerformanceCount As Currency) As Long
Private Declare Function QueryPerformanceFrequency Lib "kernel32" (lpFrequency As Currency) As Long

Private Sub Command1_Click()
    
    Dim curStartTime As Currency
    Dim curEndTime As Currency
    Dim curFreq As Currency
    
    '高分解能パフォーマンスカウンタの周波数を取得
    If QueryPerformanceFrequency(curFreq) = 0 Then
        Beep
        MsgBox "ハードウェアが高分解能パフォーマンスカウンタをサポートしていないため測定できません!", vbCritical
        Exit Sub
    End If
    
    '開始時刻を取得
    Call QueryPerformanceCounter(curStartTime)
    
    '測定する処理
    Call AddLog
    
    '終了時刻を取得
    Call QueryPerformanceCounter(curEndTime)
    
    '結果の表示
    MsgBox "処理時間は " & CStr((curEndTime - curStartTime) / curFreq) & " 秒でした。" & vbLf & "(精度: 1/" & CStr(curFreq * 10000) & " 秒)", vbInformation, "測定結果"

End Sub

サンプル解説

まず、実際の秒数を計算するために、QueryPerformanceCounter関数で精度を取得しています。
そしてQueryPerformanceCounter関数で処理開始時刻・終了時刻を取得して、終了時刻と開始時刻の差から処理にかかった時間を算出しています。

また、精度の表示に10,000倍している理由ですが、QueryPerformanceCounter関数・QueryPerformanceCounter関数の引数は実際のところはLARGE_INTEGER型なんです。
でも、扱いが非常に面倒なので同じサイズ(64ビット)の通貨型で代用しています。
通貨型は10,000倍された整数型として格納されていますが、使用時に1/10,000されてしまうので10,000倍して実際の精度を表示させています。
処理時間の計算は結局打ち消しあうので、素直に計算しています。
(予め各値を10,000倍しても良いんですが、オーバーフローのリスクがあります)

ちなみにCPUが高分解能パフォーマンスカウンタをサポートしていない場合は、QueryPerformanceCounter関数・QueryPerformanceCounter関数ともに戻り値としてゼロを返します。(サポートしている場合はゼロ以外が返ります)


[ Window Close ]