Q:mach_absolute_time を使用して、正確な時間を測定しようとしています。これはどのような時間単位を使用するのですか。具体的に言うと、2 つの時間を測定して、後の時間から先の時間を引算したとき、どのようにすればその結果を普通の時間に変換できますか。
A:この関数は、Mach の絶対時間単位に換算した結果を返します。この単位は CPU 依存のため、単純に定数を乗じて実用値を得ることはできません。むしろ、システムに用意されている変換関数を呼び出して、実用値に変換する必要があります。
最も簡単に使用できる変換関数は、CoreServices フレームワークの AbsoluteToNanoseconds および AbsoluteToDuration です。また、NanosecondsToAbsolute および DurationToAbsolute を使用して、逆方向の変換も行えます。リスト 1 に、mach_absolute_time を使用して実用時間に直した結果を得る方法の例を示します。
リスト 1:AbsoluteToNanoseconds を使用して Mach 絶対時間をナノ秒に変換 #include <assert.h>
#include <CoreServices/CoreServices.h>
#include <mach/mach.h>
#include <mach/mach_time.h>
#include <unistd.h>
uint64_t GetPIDTimeInNanoseconds(void)
{
uint64_t start;
uint64_t end;
uint64_t elapsed;
Nanoseconds elapsedNano;
// クロックを開始する。
start = mach_absolute_time();
// getpid を呼び出す。システムコールを 1 つ呼び出すだけなので、
// これは不正確な結果を生みます。より正確な結果を得るには、
// getpid を複数回呼び出して、
// その結果を平均する必要があります。
(void) getpid();
// クロックを停止する。
end = mach_absolute_time();
// 経過時間を計算する。
elapsed = end - start;
// ナノ秒に変換する。
// AbsoluteToNanoseconds は 64 ビットの整数ではなく構造体である
// UnsignedWide を使用して動作するので、いくらかポインタ操作を行う
// 必要がある。
elapsedNano = AbsoluteToNanoseconds( *(AbsoluteTime *) &elapsed );
return * (uint64_t *) &elapsedNano;
}
注意:このコードを機能させるには、Mach 絶対時間が CoreServices の AbsoluteTime と等しくなければなりません。等値であることは、以前には文書化されていませんでしたが、現在出荷されているすべての Mac OS X において真であり、将来のバージョンでも真である予定です。
プログラムが CoreServices フレームワークを使用できない場合は、リスト 2 に示すように、mach_timebase_info から返される情報を使用して同等の変換を行うことができます。
リスト 2:mach_timebase_info を使用して Mach 絶対時間をナノ秒に変換 #include <assert.h>
#include <CoreServices/CoreServices.h>
#include <mach/mach.h>
#include <mach/mach_time.h>
#include <unistd.h>
uint64_t GetPIDTimeInNanoseconds(void)
{
uint64_t start;
uint64_t end;
uint64_t elapsed;
uint64_t elapsedNano;
static mach_timebase_info_data_t sTimebaseInfo;
// クロックを開始する。
start = mach_absolute_time();
// getpid を呼び出す。// システムコールを 1 つ呼び出すだけなので、
// これは不正確な結果を生みます。より正確な結果を得るには、
// getpid を複数回呼び出して、
// その結果を平均する必要があります。
(void) getpid();
// クロックを停止する。
end = mach_absolute_time();
// 経過時間を計算する。
elapsed = end - start;
// ナノ秒に変換する。
// これが最初の実行である場合は、タイムベースを取得する。
// ゼロの分母を持つ分数は意味をなさないので、
// denom == 0 として、sTimebaseInfo を初期化していないことを
// 示すことができる。.
if ( sTimebaseInfo.denom == 0 ) {
(void) mach_timebase_info(&sTimebaseInfo);
}
// 計算する。乗算がオーバーフローしないことを願う。
// これは固定小数点を使用する代償である。
elapsedNano = elapsed * sTimebaseInfo.numer / sTimebaseInfo.denom;
return elapsedNano;
}
注意:実用時間と Mach 絶対時間を変換できると、THREAD_TIME_CONSTRAINT_POLICY ポリシーを使用して mach_wait_until と thread_policy_set を呼び出す場合にも役立ちます。
ドキュメントの改訂履歴
掲載日: 2005-01-06 |