通信速度を表示する機能を作るときや、重い処理を実装したときに目安の終了時間を表示する機能を作るときなど、特定の処理にかかった処理時間を計測したいことがあります。
C++標準ライブラリで処理時間を計測するコード例を紹介します。
実装例
C++11で日時に関する機能が多く追加されています。C++標準ライブラリのコードだけでも処理時間を計測できます。
C++標準ライブラリを使って処理時間を計測するには、chronoライブラリを使用します。
次のコードはsomething()
関数の処理時間を計測し、ミリ秒単位と秒単位でコンソールに出力するコードです。
#include <iostream>
#include <chrono>
#include <thread>
void something()
{
// 2.5秒スリープする
std::this_thread::sleep_for(std::chrono::milliseconds(2500));
}
int main(int argc, const char * argv[])
{
// 開始日時を取得する
auto start = std::chrono::system_clock::now();
// 計測したい処理
something();
// 終了日時を取得する
auto end = std::chrono::system_clock::now();
// end - start をミリ秒単位で計算する
std::chrono::duration<double, std::milli> elapsed = end - start;
// end - start を秒単位で計算する
std::chrono::duration<double> elapsed2 = end - start;
// 結果をコンソールに出力する
std::cout << elapsed.count() << "ms" << std::endl;
std::cout << elapsed2.count() << "s" << std::endl;
return 0;
}
私の環境では次のように出力されました。
2504.99ms
2.505s
現在日時の取得
現在日時を取得するにはstd::chrono::system_clock:now()
メソッドを使用します。このメソッドを使用するにはchrono
ファイルをインクルードします。
スリープ
実行中のスレッドをスリープさせるには、std::this_thread::sleep_for()
メソッドを使用します。このメソッドは次のように定義されています。また、使用するにはthread
ファイルをインクルードします。
template< class Rep, class Period >
void sleep_for( const std::chrono::duration<Rep, Period>& sleep_duration );
引数にスリープ時間を指定します。型はstd::chrono::duration
です。コード例を見れば2500ミリ秒を指定しているということが一目で分かります。コード例のように可読性を高めるため、次のような型が定義されています。
std::chrono::nanoseconds
std::chrono::microseconds
std::chrono::milliseconds
std::chrono::seconds
std::chrono::minutes
std::chrono::hours
std::chrono::days
(C++20以降)std::chrono::weeks
(C++20以降)std::chrono::months
(C++20以降)std::chrono::years
(C++20以降)
スリープ時間として使うのは、先頭4つくらいまででしょう。
処理時間の計算
処理時間は処理の完了まで必要な時間です。つまり、処理を始める直前に開始時間を取得し、終了直後に終了時間を取得し、その2つの時間の差が処理時間です。
std::chrono::system_clock::now()
メソッドの戻り値の型はstd::chrono::time_point<std::chrono::system_clock>
です。マイナス演算子がテンプレートを使って実装されており、戻り値の型を使って、どのような単位で差を取得したいかを指定できます。
std::chrono::duration<double>
を指定すると、秒単位で値を取得できます。実際のスカラー値はcount()
メソッドで取得できます。count()
メソッドの戻り値の型はテンプレートで指定しているdouble
です。
std::chrono::duration<double, std::milli>
を指定すると、ミリ秒単位で取得できます。std::milli
というテンプレート引数でミリ秒を指定しています。処理時間で使用する可能性があるのは、次のような型があります。
std::nano
std::micro
std::milli
あまりに短い時間の計測になると、タイマー精度の問題があるので、別の高精度タイマーを使う必要があります。ここで省略します。