简单性能锁分析工具(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) 守护进程。