pg_test_timing

名称

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%)单个时间调用花费不到一微妙。平均每循环开销将更低, 低于100纳秒。这个示例来自一个Intel i7-860系统,使用TSC时钟资源,显示性能优良:

Testing timing overhead for 3 seconds.
Per loop time including overhead: 35.96 nsec
Histogram of timing durations:
< usec   % of total      count
     1     96.40465   80435604 
     2      3.59518    2999652  
     4      0.00015        126  
     8      0.00002         13  
    16      0.00000          2  

请注意,每循环时间和直方图使用的时间单位不同。当单个时间调用只能降低到一微妙(usec)解决时, 该循环可以在几纳秒内解决(nsec)。

测量执行者时间开销

当查询执行者使用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 nsec
Histogram of timing durations:
< usec   % 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纳秒的时间开销,再次是这个工具直接测量的几倍。 那么多时间开销意味着实际查询本身只花费了其中的一小部分,大多数被消耗掉了。 在这个配置中,任何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:
< usec   % 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定时器。这些定时器是毫秒精度的。

作者

Ants Aasma

又见

EXPLAIN