2024 年 9 月 26 日: PostgreSQL 17 发布!
支持版本:当前 (17) / 16 / 15 / 14 / 13 / 12
开发版本:devel
不支持版本: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 系统在 9.8 毫秒内运行了计数查询,而 EXPLAIN ANALYZE 版本则花费了 16.6 毫秒,每个版本都处理了超过 100,000 行。 这 6.8 毫秒的差异意味着每行计时开销为 68 纳秒,大约是 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 毫秒。 也就是说,计时开销为 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" 内核设置是进行此类更改的唯一方式。 即使在一些较新的系统上,您看到的时钟源选项也可能只有 "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 可能无法提供准确的计时源有几种方式,这使其变得不可靠。 较旧的系统可能具有一个随 CPU 温度变化的 TSC 时钟,使其无法用于计时。 尝试在一些较旧的多核 CPU 上使用 TSC 可能会导致报告的时间在多个核心之间不一致。 这会导致时间倒退,这是一个本程序检查的问题。 即使是最新的系统也可能无法在非常激进的节能配置下提供准确的 TSC 计时。

较新的操作系统可能会检查已知的 TSC 问题,并在发现问题时切换到较慢、更稳定的时钟源。 如果您的系统支持 TSC 时间,但没有默认使用它,则可能是出于某种正当理由而禁用的。 并且,一些操作系统可能无法正确检测所有可能的问题,或者甚至允许在已知不准确的情况下使用 TSC。

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

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

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

另请参见

EXPLAIN

提交更正

如果您在文档中发现任何不正确的内容,与您对特定功能的体验不符,或需要进一步说明,请使用 此表格 报告文档问题。