29.4.1 性能模式事件计时
性能模式事件计时是通过在服务器源代码中添加 instrumentation 实现的。instrumentation 时间事件,这样性能模式就可以提供事件所需的时间信息。还可以配置instrumentation 不收集时间信息。这一节讨论可用的计时器和它们的特点,以及计时值在事件中的表示方式。
性能模式计时器在精度和开销方面有所不同。要查看可用的计时器和它们的特点,请查看performance_timers
表格:
mysql> SELECT * FROM performance_schema.performance_timers;
+-------------+-----------------+------------------+----------------+
| TIMER_NAME | TIMER_FREQUENCY | TIMER_RESOLUTION | TIMER_OVERHEAD |
+-------------+-----------------+------------------+----------------+
| CYCLE | 2389029850 | 1 | 72 |
| NANOSECOND | 1000000000 | 1 | 112 |
| MICROSECOND | 1000000 | 1 | 136 |
| MILLISECOND | 1036 | 1 | 168 |
| THREAD_CPU | 339101694 | 1 | 798 |
+-------------+-----------------+------------------+----------------+
如果与给定计时器名称相关的值为 NULL
,那么该计时器在您的平台上不可用。
列的含义如下:
-
TIMER_NAME
列显示可用的计时器名称。CYCLE
指的是基于 CPU(处理器)周期计数器的计时器。 -
TIMER_FREQUENCY
表示计时器单位每秒的频率。对于基于周期的计时器,频率通常与 CPU 速度相关。显示的值是在 2.4GHz 处理器系统上获得的。其他计时器基于固定秒的分数。 -
TIMER_RESOLUTION
表示计时器单位的增加值。如果计时器的分辨率为 10,它的值将每次增加 10。 -
TIMER_OVERHEAD
是获取一个计时值的最小 CPU 周期数。每个事件的开销是两倍于显示的值,因为计时器在事件开始和结束时被调用。
性能模式将计时器分配如下:
-
等待计时器使用
CYCLE
。 -
空闲、阶段、语句和事务计时器使用
NANOSECOND
在可用的平台上,否则使用MICROSECOND
。
在服务器启动时,性能模式验证在构建时关于计时器分配的假设,并在计时器不可用时显示警告。
为了计时等待事件,重要的标准是减少开销,以可能的代价是计时不准确,所以使用 CYCLE
计时器是最好的。
语句(或阶段)的执行时间通常是执行单个等待的时间的几个数量级。为了计时语句,重要的标准是有一个准确的测量,这不受处理器频率变化的影响,所以使用不基于周期的计时器是最好的。语句的默认计时器是 NANOSECOND
。相比于 CYCLE
计时器,额外的 “overhead” 并不重要,因为在调用计时器两次(一次在语句开始,一次在语句结束)时的开销是语句执行时间的几个数量级。使用 CYCLE
计时器没有益处,只有缺点。
cycle 计数器的精度取决于处理器速度。如果处理器运行在 1 GHz (每秒 1 亿次) 或更高,cycle 计数器可以提供亚纳秒级别的精度。使用 cycle 计数器比获取实际时间要便宜。例如,标准 gettimeofday()
函数可能需要数百个周期,这对于可能每秒数千次或数百万次执行的数据收集来说是不可接受的开销。
cycle 计数器也存在一些缺点:
-
用户期望看到的时间单位是 wall-clock 单位,例如秒的分数。将 cycles 转换为秒的分数可能会很昂贵。因此,这个转换是一个快速的乘法操作。
-
处理器的 cycle 率可能会变化,例如当笔记本电脑进入节能模式或 CPU 为了减少热生成而减速。如果处理器的 cycle 率波动,转换从 cycles 到实际时间单位将受到错误的影响。
-
cycle 计数器可能不可靠或不可用,取决于处理器或操作系统。例如,在 Pentium 上,指令是
RDTSC
(一种汇编语言指令,而不是 C 指令),操作系统理论上可以防止用户模式程序使用它。 -
一些处理器的细节相关于乱序执行或多处理器同步可能会使计数器看起来快或慢到 1000 个周期。
MySQL 支持 cycle 计数器在 x386 (Windows、macOS、Linux、Solaris 和其他 Unix 风格) 上、PowerPC 和 IA-64 上。
Performance Schema 表中的当前事件和历史事件行有三个列来表示时间信息:TIMER_START
和 TIMER_END
表示事件开始和结束,TIMER_WAIT
表示事件持续时间。
setup_instruments
表中有一个 ENABLED
列来指示要收集事件的工具。该表还有一個 TIMED
列来指示哪些工具被计时。如果一个工具不可用,它将不生产事件。如果一个可用的工具不可被计时,事件将有 NULL
值为 TIMER_START
、TIMER_END
和 TIMER_WAIT
时间值。这将导致这些值在计算汇总表中的时间值时被忽略。
事件中的时间是以 timer 在事件开始时选择的单位存储的。从 Performance Schema 表中检索事件时,时间将以 picoseconds (十亿分之一秒) 显示,以 normalize 到一个标准单位,无论选择的 timer 是什么。
timer 基线(““time zero””)发生在 Performance Schema 初始化期间,服务器启动时。TIMER_START
和 TIMER_END
值在事件中表示 picoseconds 自基线。TIMER_WAIT
值是持续时间在 picoseconds。
事件中的-pic秒值是近似值。它们的准确性受通常与单位之间的转换相关的错误形式的影响。如果使用CYCLE
计时器,并且处理器的速度变化,可能会出现漂移。因此,在服务器启动后事件的TIMER_START
值不能被看作是时间的准确测量。反之,使用TIMER_START
或TIMER_WAIT
值在ORDER BY
子句中排序事件是合理的。
选择事件中的-pic秒值,而不是微秒值的原因是性能考虑。实现目标之一是显示结果在统一的时间单位,无论计时器是什么。理想情况下,这个时间单位将像墙钟单位一样,且精度较高。但是,要将周期或纳秒转换为微秒,需要对每个instrument进行除法操作。除法在许多平台上是昂贵的。乘法不是昂贵的,因此使用了乘法。因此,时间单位是最高可能的TIMER_FREQUENCY
值的整数倍,使用一个足够大的乘数,以确保没有主要精度损失。结果是时间单位是-pic秒。这一精度是虚假的,但是这个决定使得overhead最小化。
在等待、阶段、语句或事务事件执行时,相应的当前事件表显示当前事件计时信息:
events_waits_current
events_stages_current
events_statements_current
events_transactions_current
为了确定尚未完成的事件已经运行了多长时间,计时器列被设置如下:
-
TIMER_START
被填充。 -
TIMER_END
被填充当前计时器值。 -
TIMER_WAIT
被填充当前事件已经运行的时间(TIMER_END
-TIMER_START
)。
尚未完成的事件的END_EVENT_ID
值为NULL
。要评估事件已经运行的时间,请使用TIMER_WAIT
列。因此,要确定尚未完成的事件已经运行了多长时间,可以使用以下表达式在查询中:
WHERE END_EVENT_ID IS NULL AND TIMER_WAIT > N
事件识别,如前所述,假设相应的instrument已经ENABLED
和TIMED
设置为YES
,并且相关的消费者已经启用。