pg_test_timing — 時間計測のオーバーヘッドを測定する
pg_test_timing
[option
...]
pg_test_timingはシステム上の時間計測のオーバーヘッドを測定し、またシステム時計が逆向きに進まないことを確認するためのツールです。
時間のデータの収集に時間のかかるシステムでは、EXPLAIN ANALYZE
の結果が不正確になることがあります。
pg_test_timingでは、以下のコマンド行オプションを指定できます。
-d duration
--duration=duration
テストの時間を秒単位で指定します。 時間を長くすると、少しだけ結果が正確になり、またシステム時計が逆方向に進む問題を検出できる可能性が高くなります。 デフォルトのテスト時間は3秒です。
-V
--version
pg_test_timingのバージョンを表示して終了します。
-?
--help
pg_test_timingのコマンドライン引数についてのヘルプを表示して終了します。
良い結果では、個々の時間計測のほとんど(90%以上)が1マイクロ秒未満になります。 ループあたりの平均オーバーヘッド(per loop time)の値はさらに小さく、100ナノ秒未満になります。 以下の例はIntel i7-860システムでTSC時計を使ったもので、非常に良い性能を示しています。
Testing timing overhead for 3 seconds. Per loop time including overhead: 35.96 ns Histogram of timing durations: < us % of total count 1 96.40465 80435604 2 3.59518 2999652 4 0.00015 126 8 0.00002 13 16 0.00000 2
ループあたりの時間(per loop time)とヒストグラム(histogram)で時間の単位が異なることに注意して下さい。 ループは数ナノ秒(ns)以内の精度を持つことができますが、個々の時間計測の呼び出しは1マイクロ秒(us)までの精度にしかできません。
問い合わせエグゼキュータがEXPLAIN ANALYZE
を使って文を実行するとき、要約を表示する他に、個々のオペレーションについての時間計測もされます。
次のpsqlプログラムで行を数えれば、システムのオーバーヘッドを調べることができます。
CREATE TABLE t AS SELECT * FROM generate_series(1,100000); \timing SELECT COUNT(*) FROM t; EXPLAIN ANALYZE SELECT COUNT(*) FROM t;
測定に使ったi7-860システムでは、countの問い合わせを9.8ミリ秒で実行しましたが、EXPLAIN ANALYZE
をつけたときは16.6ミリ秒かかりました。どちらの問い合わせもちょうど10万行を処理しています。
この6.8ミリ秒の差は、行あたりの時間計測のオーバーヘッドが68ナノ秒であることを示しており、これはpg_test_timingによる推定値の約2倍です。
この比較的小さな量のオーバーヘッドでも、countの文の完全な時間計測をすると70%長くかかりました。
もっと本質的な問い合わせでは、時間計測のオーバーヘッドはあまり問題にならないでしょう。
一部の新しいLinuxシステムでは、時間データの収集に使う時計をいつでも変更することができます。 2番目の例は、時間の測定源を、より遅いacpi_pmに変更することで、上の速い結果で使われたのと同じシステムでも、遅い結果が出るかもしれないことを示しています。
# cat /sys/devices/system/clocksource/clocksource0/available_clocksource tsc hpet acpi_pm # echo acpi_pm > /sys/devices/system/clocksource/clocksource0/current_clocksource # pg_test_timing Per loop time including overhead: 722.92 ns Histogram of timing durations: < us % of total count 1 27.84870 1155682 2 72.05956 2990371 4 0.07810 3241 8 0.01357 563 16 0.00007 3
この構成では、上のEXPLAIN ANALYZE
の例の実行に115.9ミリ秒かかりました。
つまり、時間計測に1061ナノ秒のオーバーヘッドとなりますが、やはりこのユーティリティによって直接測定したものに小さな数を掛けた程度の値です。
この大きな時間計測のオーバーヘッドは、実際の問い合わせ自体は問い合わせに要した時間の本の一部を占めるだけで、大半はオーバーヘッドによって使われている、ということを示しています。
この構成では、多くの時間計測オペレーションを含むEXPLAIN ANALYZE
の合計は、時間計測のオーバーヘッドにより非常に大きな値になるでしょう。
FreeBSDでも時間の測定源を実行時に変更することができ、起動時に、選択されたタイマーに関する情報をログ出力します。
# dmesg | grep "Timecounter" Timecounter "ACPI-fast" frequency 3579545 Hz quality 900 Timecounter "i8254" frequency 1193182 Hz quality 0 Timecounters tick every 10.000 msec Timecounter "TSC" frequency 2531787134 Hz quality 800 # sysctl kern.timecounter.hardware=TSC kern.timecounter.hardware: ACPI-fast -> TSC
他のシステムでは、起動時にのみ時間の測定源を設定することができます。 古いLinuxシステムでは"clock"のカーネル設定が、この種の変更をする唯一の方法でした。 比較的新しいLinuxでも、時計についての唯一のオプションが"jiffies"であるということもあります。 jiffesはLinuxの古いソフトウェア時計の実装で、十分に速い時間測定のハードウェアがあれば、以下の例のように良い精度を出すことができます。
$ cat /sys/devices/system/clocksource/clocksource0/available_clocksource jiffies $ dmesg | grep time.c time.c: Using 3.579545 MHz WALL PM GTOD PIT/TSC timer. time.c: Detected 2400.153 MHz processor. $ pg_test_timing Testing timing overhead for 3 seconds. Per timing duration including loop overhead: 97.75 ns Histogram of timing durations: < us % of total count 1 90.23734 27694571 2 9.75277 2993204 4 0.00981 3010 8 0.00007 22 16 0.00000 1 32 0.00000 1
コンピュータでの正確な時間情報の収集は通常はハードウェアクロックを用いて行われ、その正確さのレベルは様々です。 一部のハードウェアでは、オペレーティングシステムはシステムクロックの時間をほぼ直接にプログラムに渡すことができます。 システムクロックは、ある一定の時間ごとの単純な時間の割り込みを起こすチップによって提供されることもあります。 いずれの場合でも、オペレーティングシステムのカーネルは、これらの詳細を隠して時間の測定源を提供します。 しかし時間の測定源の正確さ、および結果を返す速さは、その基となっているハードウェアに依存して変わります。
時間を正確に保つことができないと、システムが不安定になることがあります。 時間の測定源へのすべての変更について、非常に注意深く検査してください。 オペレーティングシステムのデフォルトは、正確であることよりも信頼できることを重視して設定されているかも知れません。 仮想マシンを使っている場合は、それと互換性があるとして推奨されている時間の測定源を調べてください。 仮想マシンではタイマーをエミュレートするのに通常以上の困難があり、ベンダーによって推奨されるオペレーティングシステムごとの設定があることもあります。
タイムスタンプカウンタ(TSC)は、現行世代のCPU上で利用可能な最も正確な時間の測定源です。 オペレーティングシステムがTSCクロックをサポートしていて、それが信頼出来るなら、システム時間をTSCで測ることが望ましいです。 TSCが正確な時間測定源とならず、信頼できなくなる場合がいくつかあります。 古いシステムでは、TSCの時計がCPUの温度に依存して変化するため、時間測定には利用できません。 一部の古いマルチコアCPUでTSCを使うと、複数のコアの間で一貫しない時間が得られることがあります。 この場合、時計が逆戻りすることがありますが、それがこのプログラムが検査対象としている問題の1つです。 また最新のシステムでも、非常に積極的に電力節減を実施する設定の場合には、TSCの時間計測が不正確になることがあります。
新しいオペレーティングシステムには、既知のTSCの問題について検査し、問題が検出されると、遅いが、より安定した時間測定源を使うようにするものもあります。 システムがTSC時計をサポートしているけれど、それがデフォルトになっていないとしたら、何らかの正しい理由によって無効にされたのかもしれません。 一部のオペレーティングシステムでは、発生しうるすべての問題について正しく検知できないかも知れませんし、またTSCが正確でないとわかっている状況でもTSCを利用可能にするかも知れません。
高精度イベントタイマー(HPET)は、それが利用可能で、TSCが不正確なシステムにおいて、望ましいタイマーです。 タイマーのチップ自体は、100ナノ秒単位の精度までプログラム可能ですが、システムクロックによっては、そこまでの正確さはないこともあります。
ACPI(Advanced Configuration and Power Interface)は電源制御(PM)タイマーを提供し、Linuxはこれをacpi_pmとして参照します。 acpi_pmを利用した時計は、最高で300ナノ秒までの精度を提供します。
古いPCハードウェアで使われていたタイマーには、8254プログラマブルインターバルタイマー(PIT)、リアルタイムクロック(RTC)、APIC(Advanced Programmable Interrupt Controller)タイマー、サイクロン(Cyclone)などがあります。 これらのタイマーは、ミリ秒の精度を目指したものです。