QueryPerformanceCounter を用いて時間を計測する
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を愛用