第15章 タイムスタンプ

15.1. ハードウェアクロック

NUMA や SMP などのマルチプロセッサーシステムには、複数のクロックソースインスタンスがあります。クロック自体とシステムイベントに対話する方法 (CPU 周波数のスケーリングや電源モードの入力など) は、リアルタイムカーネルに適したクロックソースであるかどうかを判断します。
起動時に、カーネルは利用可能なクロックソースを検出し、使用するクロックソースを選択します。希望するクロックソースは Time Stamp Counter (TSC) ですが、利用できない場合には、HPET (High Precision Event Timer) が 2 番目に適しています。ただし、すべてのシステムに HPET クロックがあり、一部の HPET クロックは信頼できない場合があります。
TSC および HPET がない場合には、ACPI Power Management Timer (ACPI_PM)、プログラム可能な間隔タイマー (PIT)、リアルタイムクロック (RTC) などがあります。最後の 2 つのオプションは、読み込むコストが大きいか、解像度が低い (時間粒度) であるため、リアルタイムカーネルに対して最適なものです。
システムで使用可能なクロックソースの一覧を表示するには、/sys/devices/system/clocksource/clocksource0/available_clocksource ファイルを表示します。
~]# cat /sys/devices/system/clocksource/clocksource0/available_clocksource
tsc hpet acpi_pm
上記の出力例では、TSC、HPET、および ACPI_PM クロックソースが利用可能です。
現在使用中のクロックソースは、/sys/devices/system/clocksource/clocksource0/current_clocksource ファイルを読み取りて検査できます。
~]# cat /sys/devices/system/clocksource/clocksource0/current_clocksource
tsc
/sys/devices/system/clocksource/clocksource0/available_clocksource ファイルに表示されている一覧から、別のクロックソースを選択できます。これを行うには、クロックソースの名前を /sys/devices/system/clocksource/clocksource0/current_clocksource ファイルに書き込みます。たとえば、以下のコマンドは、使用中のクロックソースとして HPET を設定します。
~]# echo hpet > /sys/devices/system/clocksource/clocksource0/current_clocksource

重要

カーネルは、最適なクロックソースを選択します。選択したクロックソースの上書きは、影響が明確に理解されない限り推奨されません。
TSC は通常優先されるクロックソースですが、ハードウェア実装の一部には足りない場合があります。たとえば、一部の TSC クロックは、システムがアイドル状態に切り替わったり、CPU がより深い C 状態 (電力節約状態) に入る場合や、速度または周波数のスケーリング操作を実行したときに停止することがあります。
ただし、追加のカーネルブートパラメーターを設定することで、これらの TSC の欠点の一部を回避できます。たとえば、idle=poll パラメーターはアイドル状態にならないようにクロックを強制し、processor.max_cstate=1 パラメーターによりクロックがより深い C 状態に入るのを防ぎます。ただし、どちらの場合も、システムが常に最大速度で実行されるため、電力消費量が増加することに注意してください。

注記

クロックソースの包括的なリストは、『Understanding The Linux Kernel』 by Daniel P. Bovet and Marco Cesati の 『Timing Measurements』 の章を参照してください。

15.1.1. ハードウェアクロックソースの読み取り

TSC からの読み取りは、プロセッサーからレジスターを読み取ることを意味します。HPET クロックから読み取ると、メモリー領域を読み取ることになります。TSC からの読み取りが速く、毎秒数百万のメッセージをタイムスタンプにすると、パフォーマンスが大幅に向上します。
現在のクロックソースを 10,000,000 回読み取りする簡単なプログラムを行で使用し、利用可能なクロックソースの読み取りに必要な期間を確認できます。

例15.1 ハードウェアクロックソースの読み込みコストの比較

この例では、cat コマンドの出力で示されているように、現在使用中のクロックソースは TSC です。この time コマンドは、クロックソースを 10 万回読み込むのに必要な期間を表示するために使用されます。
~]# cat /sys/devices/system/clocksource/clocksource0/current_clocksource
tsc
~]# time ./clock_timing

	real	0m0.601s
	user	0m0.592s
	sys	0m0.002s
クロックソースは HPET に変更され、1,000 万のタイムスタンプの生成に必要な期間を比較します。
~]# echo hpet > /sys/devices/system/clocksource/clocksource0/current_clocksource
~]# cat /sys/devices/system/clocksource/clocksource0/current_clocksource
hpet
~]# time ./clock_timing

	real	0m12.263s
	user	0m12.197s
	sys	0m0.001s
手順は ACPI_PM クロックソースで繰り返します。
~]# echo acpi_pm > /sys/devices/system/clocksource/clocksource0/current_clocksource
~]# cat /sys/devices/system/clocksource/clocksource0/current_clocksource
acpi_pm
~]# time ./clock_timing

	real	0m24.461s
	user	0m0.504s
	sys	0m23.776s
time(1) man ページには、コマンドの使用方法と、その出力の解釈方法の詳細情報が記載されています。上記の例では、以下のカテゴリーを使用しています。
  • real: プログラム呼び出しからプロセスが終了するまでに費やされた合計時間。real には、usersys 時間が含まれます。通常は、後の 2 つの合計よりも大きくなります。このプロセスが優先度の高いアプリケーションや、ハードウェア割り込み (IRQ) などのシステムイベントによって中断される場合、この時間も待機に費やされた時間も real 下で計算されます。
  • user: プロセスがユーザー空間で費やした時間。カーネルの介入を必要としないタスクを実行します。
  • sys: ユーザープロセスで必要なタスクの実行中にカーネルが費やした時間。これらのタスクには、ファイルのオープン、ファイルまたは I/O ポートの読み取りおよび書き込み、メモリーの割り当て、スレッドの作成、およびネットワーク関連のアクティビティーが含まれます。
例15.1「ハードウェアクロックソースの読み込みコストの比較」 の結果から分かるように、タイムスタンプの生成の効率は、TPC、HPET、ACPI_PM です。これは、HPEET および ACPI_PM タイマーから時間値にアクセスするためのオーバーヘッドが増加するためです。