目次

QueryPerformanceCounter を用いて時間を計測する - C#

QueryPerformanceCounter を用いて時間を計測するコードを紹介します。

概要

QueryPerformanceCounter()関数を呼び出す、高分解能パフォーマンスカウンタの現在の値が取得できます。また、QueryPerformanceFrequency()関数を呼び出すと高分解能パフォーマンスカウンタの周波数が取得できます。周波数とは1秒間で増加するパフォーマンスカウンタの値です。時間を計測する開始時のパフォーマンスカウンタの値と、終了時のパフォーマンスカウンタの値の差を求め、周波数で割ることで所要時間を計算できます。

プログラム

UI

下図のUIを作成します。MultiLinesプロパティをtrueに設定したテキストボックスとButtonを2つ配置します。

コード

下記のコードを記述します。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace QueryPerformanceCounterDemo
{
  public partial class FormMain : Form
  {
    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool QueryPerformanceCounter(out long lpPerformanceCount);

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool QueryPerformanceFrequency(out long frequency);

    long freq;

    public FormMain()
    {
      InitializeComponent();
    }

    private void FormMain_Load(object sender, EventArgs e)
    {
      bool ret = QueryPerformanceFrequency(out freq);
      if (ret == false) {
        textBox_Output.Text += "QueryPerformanceFrequency() の呼び出しに失敗\r\n";
      }
      else {
        textBox_Output.Text += string.Format("QueryPerformanceFrequency() カウンタの周波数 : {0:#,0}\r\n", freq);
      }
    }

    private void button1_Click(object sender, EventArgs e)
    {
      long count;
      bool ret = QueryPerformanceCounter(out count);
      if (ret == false) {
        textBox_Output.Text += "QueryPerformanceCounter() の呼び出しに失敗\r\n";
      }
      else {
        textBox_Output.Text += string.Format("QueryPerformanceCounter() カウンタ値 : {0:#,0}\r\n",count);
      }
      
    }

    private void button2_Click(object sender, EventArgs e)
    {
      long startcount;
      QueryPerformanceCounter(out startcount);

      int num = 0;
      for (int i = 0; i < 100; i++) {
        for (int j = 0; j < 100; j++) {
          num += i * j + j;
        }
        textBox_Output.Text += string.Format("{0:d}.", num);
      }

      textBox_Output.Text += "\r\n\r\n";
      long endcount;
      QueryPerformanceCounter(out endcount);

      double sec = (double)(endcount - startcount) / (double)freq;
      textBox_Output.Text += string.Format("処理時間:{0:f} 秒\r\n",sec);
      
    }
  }
}

解説

Form_Load
private void FormMain_Load(object sender, EventArgs e)
{
  bool ret = QueryPerformanceFrequency(out freq);
  if (ret == false) {
    textBox_Output.Text += "QueryPerformanceFrequency() の呼び出しに失敗\r\n";
  }
  else {
    textBox_Output.Text += string.Format("QueryPerformanceFrequency() カウンタの周波数 : {0:#,0}\r\n", freq);
  }
}
フォームのロード時にQueryPerformanceFrequency()関数を呼び出し、パフォーマンスカウンタの周波数を取得します。取得した周波数をテキストボックスに表示します。
Button1_Click
private void button1_Click(object sender, EventArgs e)
{
  long count;
  bool ret = QueryPerformanceCounter(out count);
  if (ret == false) {
    textBox_Output.Text += "QueryPerformanceCounter() の呼び出しに失敗\r\n";
  }
  else {
    textBox_Output.Text += string.Format("QueryPerformanceCounter() カウンタ値 : {0:#,0}\r\n",count);
  }
}
ボタン(Button1)をクリックすると、QueryPerformanceCounter()関数を呼び出し、現在のパフォーマンスカウンタの値をテキストボックスに表示します。
Button2_Click
private void button2_Click(object sender, EventArgs e)
{
  long startcount;
  QueryPerformanceCounter(out startcount);

  int num = 0;
  for (int i = 0; i < 100; i++) {
    for (int j = 0; j < 100; j++) {
      num += i * j + j;
    }
    textBox_Output.Text += string.Format("{0:d}.", num);
  }

  textBox_Output.Text += "\r\n\r\n";
  long endcount;
  QueryPerformanceCounter(out endcount);

  double sec = (double)(endcount - startcount) / (double)freq;
  textBox_Output.Text += string.Format("処理時間:{0:f} 秒\r\n",sec);
}
ボタン(Button2)をクリックすると、forループで計算処理を実行します。処理前と処理後にQueryPerformanceCounter()関数を呼び出し、パフォーマンスカウンタの値の差をとり、周波数で割り所要時間を求めます。結果をテキストボックスに表示します。

実行結果

プロジェクトを実行します。下図のウィンドウが表示されます。テキストボックスに高分解能パフォーマンスカウンタの周波数が表示されます。


[Button1]ボタンをクリックします。クリックするごとに現在のパフォーマンスカウンタの値がテキストボックスに表示されます。



[Button2]ボタンをクリックします。forループによる計算が実行され、計算に要した時間がテキストボックスに表示されます。

著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
掲載日: 2014-05-19
iPentec all rights reserverd.