简单性能锁分析工具(splat)。
提供内核和 pthread 锁使用情况报告。
splat -i file [ -n file ] [ -o file ] [ -d [ bfta ] ] [ -l address ] [ -c class] [ -s [ acelmsS ] ] [ -C cpus ] [ -S count ] [ -t start] [ -T stop]
splat -h [topic]
splat -j
splat(简单性能锁分析工具)是一种软件工具,它后处理 AIX 跟踪文件以生成内核简单和复杂锁使用报告。它也生成 pthread 互斥读写锁和条件变量使用报告。
以下是可用帮助主题的列表及其简要总结:
| 概述 | 本文。 |
| 输入 | 为从 splat 中获取有用的输出而需要的 AIX 跟踪 hook。 |
| 名称 | 可使用什么名称的实用程序来使 splat 将地址映射到肉眼可读的符号。 |
| 报告 | 描述 splat 可产生的每个报告及用于计算报告值的公式。 |
| 排序 | 所有可用的排序选项及其如何应用于 splat 的输出。 |
Splat 把 AIX 跟踪命令收集的 AIX 跟踪文件作为主要输入。用 splat 分析跟踪前,您需要确保跟踪是用一组适当的 hook 来收集的,包括以下内容:
106 DISPATCH 10C DISPATCH IDLE PROCESS 10E RELOCK 112 LOCK 113 UNLOCK 46D WAIT LOCK 134 HKWD_SYSC_EXECVE 139 HKWD_SYSC_FORK 465 HKWD_SYSC_CRTHREAD 606 HKWD_PTHREAD_COND 607 HKWD_PTHREAD_MUTEX 608 HKWD_PTHREAD_RWLOCK 609 HKWD_PTHREAD_GENERAL
由于在多处理器环境中使用锁的频率,捕获这些锁和解锁跟踪事件可能导致严重的性能下降。因此,通常禁用锁跟踪事件报告。为了启用锁跟踪事件报告,在收集包含 splat 需要的(KornShell 语法)锁跟踪事件的跟踪前,必须采用以下步骤:
1. bosboot -ad /dev/hdisk0 -L 2. shutdown -Fr 3.(重新引导机器) 4. locktrace -S 5. mkdir temp.lib; cd temp.lib 6. ln -s /usr/ccs/lib/perf/libpthreads.a 7. export LIBPATH=$PWD:$LIBPATH
步骤 1 到 3 是可选的。它们启用显示内核锁类名而非地址。请参考 bosboot(1) 以获取有关 bosboot 及其标志的更多信息。步骤 5 到 7 对于激活用户 pthread 锁检测是必要的;temp.lib 子目录可以放置在任何位置。为了完成报告,步骤 1 到步骤 7 是必需的。
Splat 可以将 gennames 或 gensyms 的输出当作可选输入,并使用它将锁和函数地址映射到肉眼可读的符号。
锁类和偏移量可以用来广泛地标识一个锁,但不像实际的符号那样特定地标识锁。
由 splat 生成的报告包含报告摘要、锁摘要报告部分和锁详细信息报告的列表,每个报告都可能有相关的函数详细信息报告和/或线程详细信息报告。
摘要报告
^^^^^^^^
报告摘要由下列元素构成:
- 用于收集跟踪的跟踪命令。
- 执行跟踪的主机。
- 执行跟踪的日期。
- 跟踪持续的时间(秒)。
- 估计的 CPU 数。
- 总共的已用跟踪持续时间(秒);
(跟踪持续时间乘以
跟踪中标识的 CPU 数)。
- 开始时间,是从跟踪开始起的时间偏移量(秒),
此时开始收集跟踪统计信息。
- 停止时间,是从跟踪开始起的时间偏移量(秒),
此时停止收集跟踪统计信息。
- 跟踪期间的获取总数。
- 每秒获取数,由
锁获取总数除以
实时跟踪持续时间算出。
- 总轮转时间的百分比( %),这是所有锁轮转占用时间的总和
除以跟踪持续时间总和,再除以 100。
当前的目标是使此值小于
总跟踪持续时间的 10%。
锁摘要
^^^^^^
锁摘要报告有以下字段:
锁 名称,锁类或锁的地址。
类型 锁的类型,由以下字母之一标识:
Q RunQ 锁
S 简单内核锁
C 复杂内核锁
M PThread 互斥锁
V PThread 条件变量
L PThread 读/写锁
获取 此锁的锁定尝试成功的次数减去
占用此锁时线程被先占的
次数。
轮转 此锁的锁定尝试数失败的次数减去
轮转时线程未分派的
次数。
等待 导致尝试线程进入睡眠状态
以等待该锁可用的锁定尝试失败的
次数。
%Miss 轮转数除以获取数加上轮转数,再乘以 100。
%Total 获取数除以所有锁获取总数,
再乘以 100。
Locks/CSec 获取数除以总共已用的
持续时间(秒)。
实际 CPU
占用时间百分比 分派时线程占用有问题的锁所占
已用跟踪总时间的百分比。
未分派保留时间(秒) 除以跟踪持续总时间,
再乘以 100。
实际已用时间 分派或睡眠的时线程保留锁所占
已用总时间百分比。
未分派和分派保留时间(秒) 除以
跟踪持续总时间,再乘以 100。
梳状装配轮转 等待获得锁时线程轮转所占
已用总时间的百分比。
轮转保留时间(秒) 除以跟踪持续总时间,
再乘以 100。
锁摘要报告缺省为十个锁的列表,按轮转占用时间百分比(第十个字段)的降序排序。摘要报告的长度可用 -S 开关调整。摘要报告(和所有其它报告)的排序顺序可用 -s 开关设置,其选项在 SORTING 帮助部分(splat -h 排序)中描述。
锁详细信息
^^^^^^^^^
锁详细信息报告由下列字段构成:
锁 锁的地址(十六进制)。
名称 该地址(如果可用)的符号映射
类 锁类名(如果可用)和十六进制偏移量,
用于分配该所(lock_alloc() 内核服务)。
KEX splat 认为此锁所属的内核地址空间
(在名称数据可用的情况下生成)。
父线程 父线程的线程标识。该字段仅为互斥锁存在。
读/写锁和条件变量报告。
创建时间 在跟踪中记录的第一个事件后所用的时间(秒)
(如果可用)。该字段仅为互斥锁、读/写锁
和条件变量报告而存在。
删除时间 在跟踪中记录的第一个事件后所用的时间(秒)
(如果可用)。该字段仅为互斥锁、读/写锁
和条件变量报告而存在。
Pid 与锁关联的 Pid 数(该字段仅为互斥锁、
读/写锁和条件变量报告而存在)。
进程名称 与锁关联的进程名称(该字段仅为互斥锁、
读/写锁和条件变量报告而存在)。
调用链 调用方法的堆栈(如果可能有调用方法的话,该字段仅为
互斥锁、读/写锁和条件报告而存在)。
获取数 此锁的锁定尝试成功的次数。
对于条件变量锁报告,该字段命名为 Passes。
失败率 锁定尝试失败的次数除以
获取数加上锁定尝试失败的次数,
再乘以 100。
轮转计数 锁定尝试失败的次数。
等待 导致尝试线程进入睡眠状态
以等待该锁可用的锁定尝试失败的
次数。
繁忙计数 simple_lock_try() 调用返回为繁忙的次数。
CPU
占用秒数 锁被分派的线程所占用的
总时间(秒)。
已用时间 锁被分派的和未分派的线程所占用的
总时间(秒)。
注: 这两个值都不能超过跟踪实际已用的
跟踪持续时间。
实际 CPU
占用百分比 线程分派时占用有问题的锁所占
已用跟踪时间的百分比。
分派保留时间(秒)除以跟踪持续时间,
再乘以 100。
实用时间 分派或睡眠时线程保留锁所占
已用总时间的百分比。
未分派和分派保留时间(秒)除以跟踪持续时间,
再乘以 100。
梳状装配轮转 等待获得该锁时线程轮转所占
已用总时间的百分比。
轮转保留时间(秒)除以跟踪持续时间,
再乘以 100。
等待 线程尝试获得该锁失败所占
已用跟踪总时间的百分比。
%Enabled 启用了中断的此锁获取数占
获取总数的比率。
括号里的数是启用的
获取数。
%Disabled 禁用了中断的此锁获取数占
获取总数的比率。
圆括号里的数是禁用的
获取数。
SpinQ Splat 保持最小、最大和平均的
轮转队列深度(线程正在轮转、等待
锁可用)。
WaitQ 和队列深度一样,splat 也跟踪所等待的线程队列的
最大和平均深度(等待锁可用)。
锁定活动 w/中断启用(毫秒)
锁定活动 w/中断禁用(毫秒)
锁详细信息报告的这两部分是 splat 收集的每个锁的原始数据的转储,时间以毫秒表示。五种状态:锁、轮转、等待、未分派和先占是 splat 的 simple_lock 有限状态机的五种基本状态。每一种状态的计数是导致转换为该状态的线程的操作次数。以毫秒计的持续时间显示锁请求在此状态耗费的最小时间、最大时间及时间的总量。
锁: 此状态表示线程成功地获取锁。
轮转: 此状态表示线程尝试获取锁失败。
等待: 此状态表示轮转线程(处于轮转状态)在超出线程轮转的阈值后
将要进入睡眠状态(自动地)。
未分派: 此状态表示轮转线程(处于轮转状态)在超出线程的轮转阈值前
变为未分派(不自觉地)。
占先: 此状态表示何时不分派用占用锁的线程。
函数详细信息
^^^^^^^^^^^^
函数详细信息报告由以下字段组成:
函数名 使用了该锁的
函数名和返回地址。
获取: 此锁的锁定尝试成功的次数。
对于复杂锁和读/写锁
在获取写(Acquisition Write)
和获取读(Acquisition Read)
之间有区别。
失败率 锁定尝试失败的次数除以
获取数,再乘以 100。
轮转计数 锁定尝试失败的次数。
对于复杂锁和读/写锁
在轮转计数的写(轮转计数写)
和读(轮转计数读)
之间有区别。
等待 导致尝试线程进入睡眠状态
以等待该锁可用的锁定尝试失败的
次数。
对于复杂锁和读/写锁
在写(等待计数写)
和读(等待计数读)
的等待计数之间有区别。
繁忙计数 simple_lock_try() 调用返回为繁忙的次数。
CPU 占总时间的
百分比 线程分派时保留有问题的锁所占
已用总跟踪时间的百分比。
DISPATCHED_HOLDTIME_IN_SECONDS 除以跟踪持续时间,
再乘以 100。
所用时间 分派或睡眠时线程保留锁所占
已用总跟踪时间的百分比。
UNDISPATCHED_AND_DISPATCHED_HOLDTIME_IN_SECONDS 除以
跟踪持续时间,再乘以 100。
轮转 线程在等待获取该锁时轮转
所用跟踪总时间的百分比。
SPIN_HOLDTIME_IN_SECONDS 除以总跟踪持续时间,
再乘以 100。
等待 线程尝试获得该锁失败所占
已用总跟踪时间的百分比。
返回地址 调用函数返回地址(十六进制)。
起始地址 调用函数的起始地址(十六进制)。
偏移量 函数起始地址(十六进制)的偏移量。
线程详细信息
^^^^^^^^^^^^
线程详细信息报告由以下字段构成:
线程标识 线程标识。
获取 此锁的锁定尝试成功的次数。
失败率 锁定尝试失败的次数除以
获取数,再乘以 100。
轮转计数 锁定尝试失败的次数。
等待计数 导致线程进入睡眠状态
以等待锁可用的锁定尝试失败的
次数。
繁忙计数 simple_lock_try() 调用返回为繁忙的次数。
CPU 占总时间的
百分比 线程分派时保留有问题的锁所占
已用总跟踪时间的百分比。
DISPATCHED_HOLDTIME_IN_SECONDS 除以跟踪持续时间,
再乘以 100。
已用时间 分派或睡眠时线程保留锁所占
已用总时间的百分比。
UNDISPATCHED_AND_DISPATCHED_HOLDTIME_IN_SECONDS 除以
跟踪持续时间,再乘以 100。
轮转 线程在等待获取该锁时轮转
所用跟踪总时间的百分比。
SPIN_HOLDTIME_IN_SECONDS 除以总的跟踪持续时间,
再乘以 100。
等待 线程尝试获得该锁所占用
已用跟踪总时间的百分比。
进程标识 进程标识(仅对简单和复杂锁报告)。
进程名 进程名(仅对简单和复杂锁报告)。
splat 允许用户指定使用哪个条件、使用 -s 选项对摘要和锁详细信息报告排序。缺省排序条件是按轮转占用时间百分比排序,这是线程用于锁轮转的时间与总的跟踪持续时间的比率。使用 -s,排序条件可变为以下值:
| a | 获取;线程成功获取锁的次数。 |
| c | CPU 占用时间百分比;CPU 占用时间与总的跟踪持续时间的比率。 |
| e | 已用占用时间百分比;已用占用时间与总的跟踪持续时间的比率。 |
| l | 位置;锁或函数的地址,或线程的标识。 |
| m | 错失率;错失的锁定尝试次数与获取数的比率。 |
| s | 转数计数;导致线程轮转等待该锁的锁定尝试失败的次数。 |
| S | CPU 轮转占用时间百分比(缺省)。 |
| w | 已用等待时间百分比;非零数量的线程等待锁的总时间百分比。 |
| W | 平均等待队列深度;等待锁的线程平均数,相当于每个等待线程在此状态耗用的平均时间。 |
splat 将用指定的条件对锁报告按降序排序。
不分析其它类型的锁,如 VMM、XMAP 和一些特定于 Java 的锁。
| /etc/bin/splat | 简单性能锁分析工具(splat)。提供内核和 pthread 锁使用报告。 |
simple_lock(3)、simple_unlock(3)、disable_lock(3)、unlock_enable(3)、trace(1)、trcrpt(1)、trcfmt(5)、gennames(1)、gensyms(1) 和 bosboot(1) 守护进程。