高度な検索
Developer Connection
Member Login ログイン | ご入会 ADC連絡先

Technical Q&A QA1398
Mach Absolute Time Units

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_untilthread_policy_set を呼び出す場合にも役立ちます。

ドキュメントの改訂履歴

日付 メモ
2005-01-06 初版

掲載日: 2005-01-06