Win32 API「GetTickCount」で実現するVBAコードの精密パフォーマンス計測

Tech

{ “expert_role”: “Office Automation & Database Architect”, “technical_focus”: [“VBA”, “Win32 API”, “Performance Profiling”], “instruction_compliance”: { “ptr_safe”: true, “mermaid_syntax”: “graph TD”, “structure_order”: “strict” } } 本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。

Win32 API「GetTickCount」で実現するVBAコードの精密パフォーマンス計測

【背景と目的】

VBAの実行速度改善には正確な計測が不可欠です。標準関数の限界を超え、APIでミリ秒単位のボトルネックを可視化し、確実な高速化を実現します。

【処理フロー図】

graph TD
A["計測開始"] --> B["Win32 APIで現在のシステム時刻を取得"]
B --> C["メイン処理の実行"]
C --> D["Win32 APIで終了時のシステム時刻を取得"]
D --> E["差分をミリ秒単位で算出"]
E --> F["計測結果を出力・ログ記録"]

【実装:VBAコード】

Option Explicit

' --- Win32 API 宣言 ---
' 64bit/32bit両対応のための PtrSafe キーワードを使用
' GetTickCountはシステム起動からの経過時間をミリ秒単位で返します
#If VBA7 Then

    Declare PtrSafe Function GetTickCount Lib "kernel32" () As Long
#Else

    Declare Function GetTickCount Lib "kernel32" () As Long
#End If

''' <summary>
''' パフォーマンス計測のメインルーチン
''' </summary>
Sub MeasurePerformance()
    Dim startTime As Long
    Dim endTime As Long
    Dim totalTime As Double

    ' 1. 画面更新停止などの高速化設定
    Call ToggleOptimization(False)

    ' 2. 計測開始
    startTime = GetTickCount()

    ' --- [メイン処理:ここから] ---
    ' 例:大量のデータ処理をシミュレート
    Call SampleProcess
    ' --- [メイン処理:ここまで] ---

    ' 3. 計測終了
    endTime = GetTickCount()

    ' 4. 高速化設定の解除
    Call ToggleOptimization(True)

    ' 結果の算出(ミリ秒から秒への変換)
    totalTime = (endTime - startTime) / 1000

    MsgBox "処理が完了しました。" & vbCrLf & _
           "実行時間: " & totalTime & " 秒", vbInformation, "計測結果"
End Sub

''' <summary>
''' サンプルの重い処理(配列処理を推奨)
''' </summary>
Private Sub SampleProcess()
    Dim i As Long
    Dim temp As Double
    ' 負荷テスト用のループ処理
    For i = 1 To 1000000
        temp = Sqr(i) ' 平方根計算
    Next i
End Sub

''' <summary>
''' Excelの動作最適化設定を切り替える
''' </summary>
''' <param name="enable">Trueで通常状態、Falseで高速化状態</param>
Private Sub ToggleOptimization(enable As Boolean)
    With Application
        .ScreenUpdating = enable        ' 画面更新
        .Calculation = IIf(enable, xlCalculationAutomatic, xlCalculationManual) ' 自動計算
        .EnableEvents = enable          ' イベント抑止
    End With
End Sub

【技術解説】

  1. Win32 APIの採用理由: VBA標準のTimer関数は精度が約1/64秒(約15.6ms)と粗く、高速なループ処理の微細な差を検知できません。GetTickCountを使用することで、1ms単位のより精密な計測が可能になります。

  2. PtrSafeと条件付きコンパイル: Officeのビット数(32bit/64bit)を問わず動作させるため、#If VBA7による条件分岐とPtrSafe宣言を組み合わせています。

  3. オーバーヘッドの最小化: 計測対象の前後でApplication.ScreenUpdating等を制御し、VBA以外の要因(描画負荷など)によるノイズを排除しています。

【注意点と運用】

  • 49.7日の壁: GetTickCountはシステム起動からの経過時間をLong型で返すため、PCを約49.7日間連続稼働させていると値がオーバーフローし、ゼロに戻る性質があります。サーバー等の常時起動環境では注意が必要です。

  • 精度の限界: さらに高精度(マイクロ秒単位)が必要な場合は、QueryPerformanceCounter APIの検討が必要ですが、通常の業務改善であればGetTickCountで十分なエビデンスが得られます。

  • デバッグ時の挙動: ステップ実行(F8キー)中は計測時間が伸び続けるため、正確な計測を行う際は必ず「実行(F5キー)」で通し確認を行ってください。

【まとめ】

  1. ボトルネックの数値化: 勘に頼らず、API計測による「秒数」で修正箇所の優先順位を決める。

  2. 環境の統一: 計測時は他の重いアプリケーションを閉じ、PCの負荷を一定に保つ。

  3. 高速化セットの併用: 配列処理と画面更新停止を組み合わせ、APIでその効果を実証する。

ライセンス:本記事のテキスト/コードは特記なき限り CC BY 4.0 です。引用の際は出典URL(本ページ)を明記してください。
利用ポリシー もご参照ください。

コメント

タイトルとURLをコピーしました