涼の成長記録

自らの人生に主導権を持つべく、独立を目指して2014年3月31日を持ってITエンジニアを退職。そんな23歳♂の成長記録。

Windows, C++ で処理時間を計測。そしてtimeBeginPeriod()。

計測

今改修しようとしているアプリケーションで、様子のおかしなスレッドに出会いました。今日も素敵な出会いに乾杯です。具体的には、100msec周期で実行されることを期待しているスレッドが、どう考えても1秒に8回ぐらいしか実行されていない、といった状態です。


処理時間を計測してみたので、計測のサンプルコードを記録しておきます。

#include <time.h>

void Thread::Execute() {
	clock_t startTime, endTime;

	while (!Terminated) {
		startTime = clock();

		// 複雑でながーい処理。多分20msecぐらいかかってる。

		endTime = clock();

		double margin = (double)(endTime - startTime) / CLOCKS_PER_SEC;

		Sleep(100);
	}
}

ポイントは以下の通りです。

・ time.hをインクルードする
・ clock()を使い、clock_t型の変数に、スレッド処理の開始時間と終了時間を代入
・ double型の変数に、終了時間から開始時間を減算した値を代入
・ 秒単位で取得するためには、CLOCKS_PER_SECで除算する必要がある


clock()については、以下を参照。
clock



msec単位で計測したい

しかし、上記のコードでは、綺麗にmsec単位で計測できておりません。多分。これは、Windowsのタイマーの精度が、あまり良くないからです。具体的には、Windowsデフォルトのタイマー最小精度は15msecとなっています。いや、なっているそうです。


つまり、Sleep(1)とか、Sleep(2)とかコールしても、15msec返ってこなかったりするわけです。そこで、timeBeginPeriod()という関数を使用します。
timeBeginPeriod 関数


そうすることで、Sleep(1)で1msecウエイトなんてことも可能になります。必要なくなったら、timeEndPeriod()するのはマナーです。

// タイマーの最小精度を1msecにする
timeBeginPeriod(1)

Sleep(1)

// タイマーの最小精度を戻す
timeEndPeriod(1)

timeBeginPeriodの注意点

なんて素敵なAPIなのでしょうか!と言いたいところですが、この関数は、全プロセスに対して影響するという、とんでもない爆弾を抱えています。まあ、当たり前なのですが。まず、Windowsのスレッドスケジューラの割り込み間隔が変わります。


つまり、スレッドの切り替えを頻繁に行わなければならなくなるということです。シングルプロセッサ環境で、冒頭に書いたように数msec処理を戻さないスレッド等が存在すると、間に合わなくなります。そうすると、プロセス全体としてはパフォーマンスが低下することになります。


このことを調べていると、こんな副次効果があるようで、少し面白かったですが。

当然の如く、これらの設定はグローバルなもので、システム全体に影響を及ぼす。だから、よく言われるおまじないのようなものがある。曰く、「このソフトは、Windows Media Playerと一緒に起動していると、キビキビ動くようになるぜ」といった類のおまじないだ。Windows Media Playerは、音声や動画を再生するソフトウェアなので、当然の如く時間にシビアである。さもなければ、音とびやコマ落ちが発生する。それではメディアプレイヤーの役割を果たさないわけだから、WMPはtimeBeginPeriodを使う理由がある。

参考:本の虫: Google Chromeを使うとファンの回転数が上がる理由


すると、さらに「エコじゃない」という問題も出てきますね。スレッドの切り替えが頻繁に行われるということは、アイドル状態でいることができなくなるということで、消費電力も当然増えてしまうわけです。

たとえば、timeBeginPeriod API を使用してプラットフォームのタイマーの精度を向上させるアプリケーションについて考えてみましょう。その場合、プラットフォームのタイマー チックの精度が向上し、プロセッサが低消費電力のアイドル モードを効率的に使用できなくなります。1 つのアプリケーションでタイマー精度が 1ms まで向上した状態が保たれると、一般的なノートブック PC の場合は、バッテリの寿命に最大 10% の影響が及ぶことが観察されました。

参考:Windows 7 のエネルギー効率 - マイクロソフトのEngineering Windows 7 ブログ - Site Home - MSDN Blogs


要するに、よく考えて使わないと駄目よってことですね。私のような知識のないプログラマーは本当に注意が必要です。社内でも「Sleepの精度が上がるからやっとけ」みたいな感じで、このAPIをコールしているアプリを見かけますが、いかがなものでしょうか。


そんな感じで、お勉強になりました。
ではでは。