it-swarm-ja.com

Linuxで時間を測定する-時間対クロック対getrusage対clock_gettime対gettimeofday対timespec_get?

timeclockgetrusageclock_gettimegettimeofday、およびtimespec_getのタイミング関数の中で、それらの実装方法とどのような状況でそれらを使用する必要があるかを知るための戻り値は何ですか。

まず、wall-clock valuesを返す関数を分類する必要があります-process or threads valuesを返す関数と比較してください。 gettimeofdayは壁時計値を返し、clock_gettimeは壁時計値を返しますまたは渡されたClockパラメーターに応じてプロセスまたはスレッドの値を返します。 getrusageおよびclockはプロセス値を返します。

次に、2番目の質問では、これらの関数の実装と、その結果としての正確性について検討します。これらの機能が使用するハードウェアまたはソフトウェアのメカニズム。

getrusageはカーネルティック(通常は1ミリ秒)のみを使用しているため、ミリ秒よりも正確ではないようです。正しいですか?次に、getimeofday関数は、利用可能な最も正確な基礎となるハードウェアを使用するようです。結果として、その精度は通常、最近のハードウェアではマイクロ秒です(APIのせいでこれ以上になることはありません)。 clockについては、manページで「概算」について説明していますが、どういう意味ですか? APIがナノ秒単位であるclock_gettimeについてはどうですか。基礎となるハードウェアで許可されていれば、非常に正確であるということですか?単調性はどうですか?

他の機能はありますか?

137
Manuel Selva

問題は、CおよびC++で利用可能ないくつかの異なる時間関数があり、それらのいくつかは実装間で動​​作が異なることです。また、半ば答えがたくさんあります。クロック関数のリストをプロパティと一緒にコンパイルすると、質問に適切に答えられます。開始については、私たちが探している関連するプロパティは何かを尋ねましょう。あなたの投稿を見て、私はお勧めします:

  • 時計で測定される時間は? (本物、ユーザー、システム、またはできれば壁時計ですか?)
  • 時計の精度はどのくらいですか? (s、ms、µs、またはそれ以上?)
  • 時計はどれくらいの時間後にラップアラウンドしますか?または、これを回避するためのメカニズムはありますか?
  • クロックは単調ですか、それともシステム時間の変更(NTP、タイムゾーン、夏時間、ユーザーによる変更など)によって変わりますか?
  • 上記は実装ごとにどのように異なりますか?
  • 特定の機能は時代遅れ、非標準などですか?

リストを開始する前に、ウォールクロック時間が使用するのに適切な時間であることはめったにありませんが、タイムゾーンの変更、夏時間の変更、またはウォールクロックがNTPによって同期されている場合は変更されます。イベントをスケジュールしたり、パフォーマンスをベンチマークするために時間を使用している場合、これらはどれも良いことではありません。壁(またはデスクトップ)の時計という名前が示すものにのみ適しています。

LinuxとOS Xの時計についてこれまでに見つけたものは次のとおりです。

  • time() は、OSからの実時間を秒単位の精度で返します。
  • clock() は、ユーザー時間とシステム時間の合計を返すようです。 C89以降に存在します。かつてこれはサイクル単位のCPU時間であると想定されていましたが、最新の標準 POSIXなど では、CLOCKS_PER_SECが1000000である必要があり、可能な最大精度は1 µsです。私のシステムの精度は実際には1 µsです。このクロックは、上限に達するとラップアラウンドします(通常、これは〜2 ^ 32ティック後に発生します。これは1 MHzクロックではそれほど長くありません)。 man clockは、glibc 2.18以降、Linuxのclock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...)で実装されていると言います。
  • clock_gettime(CLOCK_MONOTONIC, ...) はナノ秒の解像度を提供し、単調です。 「秒」と「ナノ秒」は、それぞれ32ビットカウンターに個別に格納されていると思います。したがって、ラップアラウンドは、数十年の稼働時間の後に発生します。これは非常に優れた時計のように見えますが、残念ながらOS Xではまだ利用できません。POSIX7 CLOCK_MONOTONICをオプションの拡張子として記述
  • getrusage() は、私の状況に最適な選択肢であることが判明しました。ユーザー時間とシステム時間を別々に報告し、ラップアラウンドしません。私のシステムの精度は1 µsですが、Linuxシステム(GCC 4.1.2を搭載したRed Hat 4.1.2-48)でもテストしましたが、精度はわずか1 msでした。
  • gettimeofday() は、(名目上)µsの精度で実時間を返します。私のシステムでは、このクロックはµsの精度を持っているように見えますが、 「システムクロックの解像度はハードウェアに依存する」 であるため、これは保証されません。 POSIX.1-2008 言う 。 「アプリケーションでは、廃止されたclock_gettime()関数の代わりにgettimeofday()関数を使用する必要があります」ので、使用しないでください。 Linux x86およびそれを実装 システムコールとして
  • mach_absolute_time() は、OS Xでの非常に高い解像度(ns)タイミングのオプションです。私のシステムでは、これは実際にns解像度を提供します。原則として、このクロックはラップアラウンドしますが、64ビットの符号なし整数を使用してnsを格納しているため、ラップアラウンドは実際には問題になりません。移植性には疑問があります。
  • ハイブリッド関数を作成しました に基づいています このスニペット Linuxでのコンパイル時にclock_gettimeを使用するか、OS Xでのコンパイル時にMachタイマーを使用して、両方のLinuxでns精度を取得しますおよびOSX。

上記のすべては、特に指定のない限り、LinuxとOS Xの両方に存在します。上記の「私のシステム」は、MacPortsのGCC 4.7.2でOS X 10.8.3を実行するAppleです。

最後に、上記のリンクに加えて、参考になった参考文献のリストを次に示します。


Update:OS Xでは、clock_gettimeが10.12(Sierra)で実装されました。また、POSIXおよびBSDベースのプラットフォーム(OS Xなど)は、rusage.ru_utime structフィールドを共有します。

183