pg_test_timing — 测量计时开销
pg_test_timing [option...]
pg_test_timing是一个用于测量系统计时开销的工具,并确认 系统时间不会倒退。收集计时数据较慢的系统,可能会给出不够精确的 EXPLAIN ANALYZE结果。
pg_test_timing接受下列命令行选项:
良好的结果应显示,大多数(>90%)单次计时调用的耗时都小于 1 微秒。每轮循环的 平均开销会更低,低于 100 纳秒。下面这个来自一台使用 TSC 时钟源的 Intel i7-860 系统的示例,展示了极佳的性能:
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
注意,每轮循环时间与柱状图使用的单位不同。循环的解析度可以达到几纳秒(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 系统上,普通计数查询耗时 9.8 ms,而 EXPLAIN ANALYZE版本耗时 16.6 ms,两者都处理了略多于 100,000 行。这 6.8 ms 的差异意味着每行的计时开销为 68 ns,大约是 pg_test_timing 估计值的两倍。即便是这样相对较小的开销,也会让完整计时的计数语 句耗时增加近 70%。对于更复杂的查询,计时开销带来的问题就不会这么明显。
在某些较新的 Linux 系统上,可以随时更改用于收集计时数据的时钟源。第二个示例展 示了在产生上述快速结果的同一台系统上,切换到较慢的 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 ms。这 意味着计时开销达到 1061 ns,同样只是本工具直接测得数值的一个小倍数。如此之大的 计时开销说明,实际查询本身只占已统计时间的一小部分,其余大多耗费在开销上。在这 种配置下,任何包含大量计时操作的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” 是进行此类更改的唯一方式。即使在某些较新的系统上,你能看到的时钟源选项也可能只 有“jiffies”。jiffies 是较早的 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 时钟可能会随 CPU 温度变化, 因此不适合用于计时。在某些较旧的多核 CPU 上使用 TSC,还可能导致不同核心报告的 时间彼此不一致。这会引起时间倒退,而本程序正是用来检查这类问题的。即便在最新的 系统上,若节能配置过于激进,也可能无法提供精确的 TSC 计时。
较新的操作系统可能会检测已知的 TSC 问题,并在发现时切换到更慢但更稳定的时钟 源。如果你的系统支持 TSC 计时却没有默认使用它,那么禁用它很可能是有充分理由的。 某些操作系统也可能无法正确检测所有潜在问题,或者即使已知 TSC 不准确,仍允许继 续使用它。
如果系统上有高精度事件计时器(HPET),并且 TSC 不准确,那么 HPET 就是系统更倾 向使用的计时器。计时器芯片本身可编程,最高可提供 100 纳秒的解析度,但在你的系 统时钟中未必能看到这么高的准确性。
高级配置与电源接口(ACPI)提供了一种电源管理(PM)计时器,Linux 将其称为 acpi_pm。由 acpi_pm 派生的时钟在最佳情况下可提供 300 纳秒的解析度。
较旧 PC 硬件使用的计时器包括 8254 可编程区间计时器(PIT)、实时时钟(RTC)、高 级可编程中断控制器(APIC)计时器以及 Cyclone 计时器。这些计时器的目标解析度是 毫秒级。
如果您发现文档中有不正确的内容、与您使用特定功能的经验不符或需要进一步说明,请使用此表单来报告文档问题。