ぬうぱんの備忘録

技術系のメモとかいろいろ

作った曲一覧はこちら

Boostのposix timeでマシンをまたぐマイクロ秒精度のタイマー

何があった

 速度測定するのにプラットフォームに依存しないミリ秒単位のタイマーが欲しくなって無理なのかなーって思ったら実はできるのかも? ってことでいろいろ試してメモ。

単一マシン上の場合

 特定の関数にかかる時間を調べてたいって言う時はboost::timer::cpu_timerを使えば良い。ナノ秒単位で使い方もとっても簡単。ここ(https://sites.google.com/site/boostjp/tips/timer)がものすごくわかりやすいのでチェック。

マシンをまたぐ場合

 要するに

  1. マシンAでタイマークラス開始
  2. マシンAでなんか処理
  3. マシンBにタイマークラスを転送
  4. マシンBでなんか処理
  5. マシンBでかかった時間を取得

 という事をしたい。cpu_timerを転送したらNGなのかは調べていないけれど、NGだろうと決めつけて別の方法をメモ。

まずはクラス化

 とりあえずクラスにまとめるとこんな感じ

class CTimer {
private:
	boost::posix_time::ptime _Now;

public:
	//現在の時刻を設定
	void Refresh(){
		_Now = boost::posix_time::microsec_clock::local_time();
	}

	// 他のタイマーからの経過時間を測定
	double Elapsed(const CTimer &tick) const{
		boost::posix_time::time_duration Diff= this->_Now-tick._Now;
		return static_cast<double>(Diff.total_microseconds())/std::pow(10.0, 6.0);
	}
};

 たったのこれだけ。
大事なのは

  • boost::posix_time::microsec_clockを使うこと
  • boost::posix_time::time_duration::total_microseconds()を使うこと

この二つ。
ちゃんとマイクロ秒単位のクロックを使うのがとっても大事。
動作の検証は

int main(void){
	MPTimer::CTimer Old;
	MPTimer::CTimer Now;

	while(true){
		Old.Current();
		cin.get();
		Now.Current();
		cout << Now.ElapsedTime(Old) << "[sec]" << endl;
	}

	return 0;
}

Enter押すとその都度経過時間を報告するだけの非常に簡単なプログラム。
もしかしたらハードウェアとかOSの設定によって秒単位とかで返されることもあるそうです。

http://stackoverflow.com/questions/6734375/c-boost-get-current-time-in-milliseconds

ネットワークで送信したらどうなるのか

 肝心のネットワーク送信した場合の動作なんですがバイト列をそのまま転送しても大丈夫でした。心配ならシリアライズしてから送信するといいんじゃないでしょうか。
 注意しないといけないのは転送するマシン間で時刻を合わせておくことくらいでしょうか。ntpとか使ってしっかり合わせましょう。
 これについてはソースコードとかは特に無いです。

補足(2013/08/27)

 boostのバージョンが若干古くてcpu_timerが使え無い(実際、ubuntu12.04のパッケージで用意されてるやつだと使えない)場合、boost::timerを代わりに使うかと思うんですが、このboost::timer、マルチスレッド環境だったり、IO待ちがあったりだと正確な秒数を報告しないという問題が。そんな状況でも、ここで紹介した方法使うと秒単位くらいなら割と正確に測ってくれます。