pg_test_timing

pg_test_timing —测量定时开销

Synopsis

pg_test_timing [ option ...]

Description

pg_test_timing 是一种工具,用于测量系统上的计时开销,并确认系统时间永远不会向后移动。收集时序数据的系统较慢,可能会产生不太准确的EXPLAIN ANALYZE结果。

Options

pg_test_timing 接受以下命令行选项:

  • -d duration
    --duration=duration

    • 指定测试持续时间,以秒为单位。持续时间越长,精度越高,并且更有可能发现系统时钟向后移动的问题。默认测试持续时间为 3 秒。
  • -V
    --version

    • 打印 pg_test_timing 版本并退出。
  • -?
    --help

    • 显示有关 pg_test_timing 命令行参数的帮助,然后退出。

Usage

Interpreting results

良好的结果将显示大多数(> 90%)单独的计时调用花费不到一微秒的时间。每个循环的平均开销将更低,低于 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)内,而单个定时调用只能解析到一微秒(us)。

测量 Actuator 定时开销

当查询执行程序正在使用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 毫秒内运行计数查询,而EXPLAIN ANALYZE版本则需要 16.6 毫秒,每个处理刚好超过 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

在这种配置下,上面的 samplesEXPLAIN ANALYZE耗时 115.9 ms。这是 1061 ns 的时序开销,再次是此 Util 直接测量的结果的一小部分。如此多的计时开销意味着实际的查询本身仅占时间的一小部分,而大部分却被消耗在开销中。在这种配置中,任何涉及许多定时操作的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 系统上,“时钟”内核设置是进行此类更改的唯一方法。甚至在一些较新的时钟源上,您将看到的唯一时钟源选项是“ 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

时钟硬件和定时精度

通常,在计算机上使用具有各种精度级别的硬件时钟来收集准确的时序信息。使用某些硬件,os 几乎可以将系统时钟时间直接传递给程序。系统时钟也可以从仅提供定时中断,某个已知时间间隔的周期性滴答的芯片中获取。无论哪种情况,os 内核都提供隐藏这些细节的时钟源。但是,该时钟源的准确性及其返回结果的速度取决于基础硬件。

不正确的时间保持会导致系统不稳定。非常仔细地测试对时钟源的任何更改。有时会设置 os 默认值,以使其可靠性高于最佳准确性。并且,如果您使用的是虚拟机,请查看与之兼容的建议时间源。虚拟硬件在仿真计时器时会面临其他困难,而且供应商通常会建议每个 os 进行设置。

时间戳计数器(TSC)时钟源是当前 CPU 上最精确的时钟源。当 os 支持并且 TSC 时钟可靠时,这是跟踪系统时间的首选方法。 TSC 有几种方法无法提供准确的计时源,因而使其不可靠。较早的系统可能具有根据 CPU 温度而变化的 TSC 时钟,从而使其无法用于计时。尝试在某些较旧的多核 CPU 上使用 TSC 可能会导致报告的时间在多个核之间不一致。这可能会导致时间倒退,这是该程序要检查的问题。而且即使是最新的系统也无法通过非常激进的节能配置来提供准确的 TSC 时序。

较新的 os 可能会检查已知的 TSC 问题,并在发现它们时切换到较慢,更稳定的时钟源。如果您的系统支持 TSC 时间,但不默认为该时间,则可能有充分的理由将其禁用。而且某些 os 可能无法正确检测所有可能的问题,或者即使在已知不准确的情况下也允许使用 TSC。

在有可用且 TSC 不准确的系统上,高精度事件计时器(HPET)是首选计时器。计时器芯片本身是可编程的,允许高达 100 纳秒的分辨率,但是您可能看不到系统时钟那么高的精度。

高级配置和电源接口(ACPI)提供了电源 Management(PM)计时器,Linux 将其称为 acpi_pm。来自 acpi_pm 的时钟充其量只能提供 300 纳秒的分辨率。

在较旧的 PC 硬件上使用的计时器包括 8254 可编程间隔计时器(PIT),实时时钟(RTC),高级可编程中断控制器(APIC)计时器和 Cyclone 计时器。这些计时器的目标是毫秒级分辨率。

See Also

EXPLAIN