Windows が提供する QueryPerformanceCounter(QPC) と QueryPerformanceFrequency(QPF)を利用した処理時間の計測方法について紹介します。
(※ これらは Windows 固有の API のため、クロスプラットフォームな対応が必要な場合は、その環境ごとに適した API を利用する必要があります。)
QPC と QPF について
QueryPerformanceCounter (QPC)
- システムが起動してからの累積カウンタ値(ティック数)を取得する関数
- 1µs(マイクロ秒)未満の精度
QueryPerformanceFrequency (QPF)
- 1 秒あたりのティック数を取得する関数
経過時間の算出
ある 2 点の QPC を QPF で割ることで、経過時間(秒)を求めることができます。
$$ \Delta QPC = QPC_{\text{end}} - QPC_{\text{start}} $$
$$ \text{Elapsed Time} = \frac{\Delta QPC}{QPF} $$
例)
QPF が 1000(1 ティック = 0.001 秒)で、QPC の開始時点と終了時点が以下のようになっているとします。
$$ QPC_{\text{start}} = 1000, \quad QPC_{\text{end}} = 1300 $$
このとき、QPC の差分(ΔQPC)は、
$$ \Delta QPC = QPC_{\text{end}} - QPC_{\text{start}} = 1300 - 1000 = 300 $$
経過時間は、QPF を用いて以下のように計算できます。
$$ \text{Elapsed Time} = \frac{\Delta QPC}{QPF} = \frac{300}{1000} = 0.3 \text{ 秒} $$
サンプルコード
#include <windows.h>
#include <stdio.h>
#include <stdint.h>
using i64 = std::int64_t;
int main()
{
i64 start = 0, end = 0, frequency = 0;
QueryPerformanceFrequency(reinterpret_cast<LARGE_INTEGER*>(&frequency));
QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(&start));
// 計測対象となる処理(ここでは 300ms スリープ)
Sleep(300);
QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(&end));
// 経過時間(秒)を算出
double elapsedSeconds = static_cast<double>(end - start) / frequency;
printf("Elapsed time: %.3f [ms]\n", elapsedSeconds * 1000.0);
return 0;
}
Elapsed time: 300.176 [ms]