第15章 タイムスタンプ

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

NUMA や SMP などのマルチプロセッサーシステムには、クロックソースのインスタンスが複数あります。CPU 周波数スケーリングや省エネモードに入るなど、クロック間で対話する方法およびシステムイベントに反応する方法によって、Realtime カーネルに適したクロックソースであるかどうかが判断されます。
カーネルはブート時に利用可能なクロックソースを検出して使用する 1 つを選択します。推奨されるクロックソースは Time Stamp Counter (TSC) ですが、これが利用できない場合は High Precision Event Timer (HPET) が 2 番目に最適なオプションです。ただし、全システムに HPET クロックが搭載されているとは限りません。また、信頼できない HPET クロックもあります。
TSC や HPET がない場合、他のオプションとしては ACPI Power Management Timer (ACPI_PM)、Programmable Interval Timer (PIT)、Real Time Clock (RTC) があります。2、3 つ目のオプションは読み取りにコストがかかるか、精度 (時間粒度) が低いため、Realtime カーネルには準最適です。
使用しているシステムで利用可能なクロックソースの一覧は、/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-state (省電力状態) に入り、速度または周波数スケーリングの動作を行う時に同期しなくなることがあります。
ただし、こうした TSC の欠点はカーネルのブートパラメーターに追加設定を行うことにより対処できます。たとえば、idle=poll パラメーターは、強制的にクロックがアイドル状態に入らないようにできます。processor.max_cstate=1 パラメーターは、クロックが深い C-state に入らないようにします。なお、どちらの場合でもシステムは常に最高速度で実行するためエネルギー消費は高くなります。

注記

クロックソースの包括的な一覧は、Daniel P. Bovet と Marco Cesati 共著の Understanding The Linux KernelTiming Measurements の章を参照してください。

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

TSC からの読み取りは、基本的にはプロセッサーから登録を読み取ることです。HPET クロックからの読み取りは、メモリ領域を読み取ることを意味します。TSC からの読み取りは速いため、毎秒何十万ものメッセージにタイムスタンプ処理を行う場合には、パフォーマンスに多大なメリットをもたらします。
現在のクロックソースを 1000 万回続けて読み取る簡易なプログラムを使用することで、利用可能なクロックソースを読み取るために必要な期間を確認できます。

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

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

	real	0m0.601s
	user	0m0.592s
	sys	0m0.002s
1000 万回のタイムスタンプを生成するために必要な期間を比較するため、クロックソースが HPET に変更されました。
# 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「ハードウェアクロックソースを読み取るコストの比較」 の結果のとおり、タイムスタンプを生成する上での効率性は、TSC、HPET、ACPI_PM の順に低くなります。これは、HPET および ACPI_PM タイマーからの時間値にアクセスするオーバーヘッドが増加するためです。