2025年9月25日: PostgreSQL 18 发布!
支持的版本:当前 (18) / 17 / 16 / 15 / 14 / 13
开发版本:devel
不支持的版本:12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2

pg_test_timing

pg_test_timing — 测量计时开销

概要

pg_test_timing [选项...]

描述

pg_test_timing 是一个工具,用于测量系统上的计时开销,并确认系统时间永不倒退。收集计时数据速度慢的系统可能导致 EXPLAIN ANALYZE 的结果不够准确。

选项

pg_test_timing 接受以下命令行选项

-d 持续时间
--duration=持续时间

指定测试的持续时间,以秒为单位。更长的持续时间可以提供更精确的测量结果,并更有可能发现系统时钟倒退的问题。默认测试持续时间为 3 秒。

-V
--version

打印 pg_test_timing 的版本并退出。

-?
--help

显示关于 pg_test_timing 命令行参数的帮助信息,并退出。

用法

结果解读

良好的结果会显示大部分(>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)。

测量执行器计时开销

当查询执行器使用 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 ms,而 EXPLAIN ANALYZE 版本耗时 16.6 ms,每个都处理了略多于 100,000 行。这 6.8 ms 的差值意味着每行的计时开销为 68 ns,大约是 pg_test_timing 估计值的两倍。即使是如此小的开销,也使得完全计时的 count 语句的执行时间增加了近 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 不准确时系统中首选的计时器。计时器芯片本身可编程,允许高达 100 纳秒的分辨率,但您的系统时钟可能无法达到如此高的精度。

高级配置和电源接口(ACPI)提供了一个电源管理(PM)计时器,Linux 将其称为 acpi_pm。从 acpi_pm 派生的时钟最好能提供 300 纳秒的分辨率。

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

另请参阅

EXPLAIN

提交更正

如果您在文档中看到任何不正确之处、与您在特定功能上的体验不符或需要进一步说明的地方,请使用 此表格 报告文档问题。