skills/perf-prof/SKILL.md
--- name: perf-prof metadata: version: "0.1" source: https://github.com/OpenCloudOS/perf-prof.git description: 使用perf-prof进行Linux系统问题分析。perf-prof是基于perf_event的系统级分析工具,事件在内存中实时处理,可长期运行。触发场景:(1) CPU使用率高、热点分析 (2) 进程状态异常(D/S状态多) (3) 延迟抖动、响应慢 (4) 内存泄露或增长异常 (5) 块设备IO慢 (6) 虚拟机性能问题 (7) 事件聚合统计 (8) 自定义脚本分析。核心分析器:profile(CPU采样)、task-state(进程状态)、multi-trace(延迟分析)、kmemleak(内存泄露)、blktrace(IO延迟)、top/sql(聚合统计)、kvm-exit(虚拟化退出)、rundelay(调度延迟)、syscalls(系统调用耗时)、python(自定义脚本分析)。适用于:性能问题定位、内核/应用开发调试、学习理解Linux内核机制
npx skillsauth add opencloudos/perf-prof skills/perf-profInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
perf-prof 是一个Linux系统级性能分析工具,基于perf_event在内存中实时处理事件。本技能提供使用perf-prof分析系统问题的工作流程和方法。
使用前先检查 perf-prof 是否已安装:
which perf-prof && perf-prof --version
如果系统中没有 perf-prof 二进制文件,需要询问用户确认是否可以下载源码并编译安装,然后执行以下步骤:
# 1. 下载源码
git clone https://github.com/OpenCloudOS/perf-prof.git
cd perf-prof
# 2. 安装依赖包
yum install -y xz-devel elfutils-libelf-devel libunwind-devel python3-devel
# 3. 编译
make
# 4. 验证安装
./perf-prof --version
操作步骤:
使用系统工具初步诊断(可选):
top -1 # 查看CPU使用率、进程状态
mpstat -P ALL 1 # 查看各CPU利用率
vmstat 1 # 查看内存、IO、CPU综合状态
iostat -x 1 # 查看磁盘IO
根据决策树选择分析器:
系统问题
├── CPU相关
│ ├── CPU使用率高 → profile (采样分析)
│ ├── 进程运行时间统计 → top (sched_stat_runtime)
│ └── CPU上运行进程监控 → oncpu
├── 调度相关
│ ├── 进程状态分析(R/S/D) → task-state
│ ├── 调度延迟分析 → rundelay
│ └── 唤醒延迟分析 → multi-trace
├── 内存相关
│ ├── 内核内存泄露 → kmemleak
│ ├── 内存分配统计 → kmemprof
| ├── 缺页异常 → page-faults
| ├── 跟踪内存写入 → breakpoint
| └── 读取内核内存 → kcore
├── IO相关
│ └── 块设备延迟 → blktrace
├── 系统调用
│ └── 系统调用耗时 → syscalls
├── 虚拟化
│ └── KVM退出延迟 → kvm-exit
├── 硬件相关
| ├── 断点分析 → breakpoint
| └── 硬件状态 → tlbstat、llcstat、hwstat
├── 事件计数
| ├── 高频计数、微突发检测 → hrcount
| └── 低频计数 → stat
├── 通用事件追踪 → trace
└── 自定义脚本分析 → python
如有必要,在选择具体分析器之前,先通过定界分析确定问题发生在用户态还是内核态,Guest还是Host:
定界分析路径:
问题定界
├── 方法1:syscalls分析系统调用耗时
│ ├── 系统调用耗时高 → 内核态问题 → 进入内核分析路径
│ └── 系统调用耗时低 → 用户态问题 → 进入用户态分析路径
│
├── 方法2:task-state分析进程运行状态
| ├── R状态(Running)占比高 → 用户态CPU消耗 → 进入用户态分析路径
| ├── S状态(Sleeping)占比高 → 等待唤醒 → 分析唤醒源
| ├── D状态(Disk Sleep)占比高 → IO/锁等待 → 进入内核分析路径
| └── RD状态(Runnable)占比高 → 调度延迟 → 进入内核分析路径
|
└── 方法3:kvm-exit分析虚拟化退出耗时
├── 虚拟化退出耗时高 → Host问题 → 进入内核分析路径
└── 虚拟化退出耗时低 → Guest问题 → 进入Guest内分析
内核态问题分析路径:
# 1. 调度延迟分析
# 2. 系统调用深入分析:哪个系统调用慢,系统调用内发生的进程切换等
# 3. IO延迟分析
# 4. 内核热点采样
# 5. 虚拟化退出耗时分析
用户态问题分析路径:
# 1. 用户态CPU热点采样
# 2. 用户态函数追踪(添加uprobe点)
# 3. 用户态函数耗时分析
# 4. 业务层面分析:结合业务日志、应用metrics等
根据问题类型选择对应分析器,必要时选择多个分析器相互验证。
以下分析器有文档,参考references/目录下的详细文档,优先通过第三步获取概要信息及示例:
R,S,D,T,t,I,RD)的耗时分布以下分析器无文档,必须通过第三步获取概要信息及示例:
按功能领域分类
profile,cpu-util,oncpukmemleak,kmemprof,page-faultstask-state,rundelay,oncpublktracekvm-exit,kvmmmu,bpf:kvm_exithwstat,llcstat,tlbstat,split-lock,ldlat-stores,ldlat-loads,breakpointirq-off,watchdogsql,python,traceexpr,misc,kcore,list,usdt,help按分析技术分类
profilehrcount,stat,percpu-stat,hrtimer,num-dist
hrcountstattop,sqlmulti-trace,nested-trace
rundelaysyscallsblktracekvm-exittask-state,oncpu
task-statetracepythonbreakpointmulti-trace,trace,python按事件依赖程度分类
misc,kcore,list,usdt,helptlbstat,llcstat,hwstat,breakpoint,kvmmmu,irq-off,page-faults,ldlat-stores,ldlat-loads,oncpu,blktrace,kvm-exit,percpu-stat,watchdog,task-state,cpu-util,profile,split-lockexpr,stat,hrcount,event-care,hrtimer,rundelay,nested-trace,syscalls,kmemprof,multi-trace,top,num-dist,kmemleak,trace,sql,pythonebpf类
bpf:kvm_exit
操作步骤:
查看分析器帮助:
perf-prof <profiler> -h
帮助信息包含:
-e事件选项阅读分析器文档:
参考references/目录下对应的md文档,获取详细用法和典型场景。
判断事件需求:
分析器类型判断:
├── 内建事件类(无需-e选项)→ 直接跳转第六步
│ 例如:profile, task-state, blktrace, kvm-exit, oncpu
└── 自定义事件类(需要-e选项,或其他需要事件的选项)→ 继续确定事件选项要求
例如:trace, top, multi-trace, kmemleak, sql
确定事件选项要求
-e, --event 选项指定事件
--alloc/--free 选项指定事件。只有kmemleak使用示例:
# 查看profile分析器帮助
perf-prof profile -h
# 查看top分析器帮助(需要-e选项)
perf-prof top -h
操作步骤:
列出系统事件:
# 列出所有tracepoint事件
perf-prof list
# 按类别筛选事件
perf-prof list | grep "^sched:" # 调度相关
perf-prof list | grep "^kmem:" # 内存相关
perf-prof list | grep "^block:" # 块设备相关
perf-prof list | grep "^syscalls:" # 系统调用相关
查看事件字段:
# 查看事件的字段定义(用于配置过滤器和表达式)
perf-prof trace -e <sys:name> help
# 示例:查看sched_wakeup事件字段
perf-prof trace -e sched:sched_wakeup help
常用事件速查: | 分析场景 | 推荐事件 | 关键字段 | |---------|---------|---------| | 进程唤醒 | sched:sched_wakeup | pid, comm, prio, target_cpu | | 进程切换 | sched:sched_switch | prev_pid, next_pid, prev_comm, next_comm | | 运行时间 | sched:sched_stat_runtime | pid, comm, runtime | | 内存分配 | kmem:kmalloc | ptr, bytes_alloc, call_site | | 内存释放 | kmem:kfree | ptr | | 软中断 | irq:softirq_entry/exit | vec | | 系统调用 | raw_syscalls:sys_enter/exit | id |
动态探针(当系统事件不满足需求时):
# kprobe - 内核函数探针
-e 'kprobe:try_to_wake_up'
# kretprobe - 内核函数返回探针
-e 'kretprobe:try_to_wake_up'
# uprobe - 用户态函数探针,二进制路径带有'/',必须使用双引号
-e 'uprobe:func@"/path/to/binary"'
# uretprobe - 用户态函数返回探针,二进制路径带有'/',必须使用双引号
-e 'uretprobe:func@"/path/to/binary"'
新增动态探针(当系统事件不满足要求且动态探针无法使用或需要增加参数时):
通过 /sys/kernel/debug/tracing/kprobe_events 和 /sys/kernel/debug/tracing/uprobe_events 文件手动新增探针。
判断新增的动态探针是内核态的还是用户态的。
详细文档:
延迟分析:选择事件原则:
根据分析需求,使用下方 事件选择语法 配置事件。
配置流程:
确定事件格式:参考 基本格式 选择事件类型
sys:namekprobe:func、uprobe:func@"file"配置过滤器(可选,内核态执行): 参考 过滤器语法 和 Event_filtering.md
# 格式:sys:name/filter/
-e 'sched:sched_wakeup/pid>1000 && prio<10/'
-e 'sched:sched_wakeup/comm~"java*"/'
配置属性(可选,用户态处理): 参考 事件属性 选择所需属性
# 格式:sys:name/filter/ATTR/ATTR/
-e 'sched:sched_wakeup//stack/' # 无过滤器,有属性
-e 'sched:sched_wakeup/pid>1000/stack/alias=wk/' # 过滤器 + 属性
配置表达式(可选,复杂计算): 参考 expr.md
# 1. 查看expr帮助
perf-prof expr -h
# 2. 属性值使用表达式
-e 'sched:sched_stat_runtime//top-by=(runtime/1000)/'
-e 'sched:sched_wakeup//key=(prio<100?pid:0)/'
延迟分析:配置key属性(可选,仅用于multi-trace): key属性用来关联延迟路径上的事件。只有相同key的事件才可以计算延迟。
Key选择的本质问题:你希望延迟路径上的事件如何关联在一起?
从事件上下文理解Key选择
每个事件发生时,都有两个基本上下文:
核心问题:延迟路径上,上下文是否变化?
| 上下文变化情况 | Key选择 | 典型场景 |
|---------------|----------|----------|
| 同CPU、同线程 | 默认(按CPU)或不指定 | 软中断、hardirq |
| 可能跨CPU、同线程 | -k common_pid 或 -p/-t | 系统调用(线程可能迁移) |
| 跨线程、可能跨CPU | key=资源标识 | 调度延迟、跨进程通信 |
Key的作用 = 在"上下文可能变化"的情况下,找到"不变的关联标识"
Key选择判断流程
问:延迟路径上的事件,线程上下文是否相同?
是 → 问:CPU上下文是否相同?
│
├── 是 → 不需要key(默认按CPU)
│ 例:软中断、本地定时器
│
└── 否 → key=common_pid,需要 --order
例:系统调用(线程可能迁移)
否 → 必须用"业务字段"作为key,需要 --order
问:什么东西从起点事件"传递"到终点事件?
│
├── 进程ID → key=pid相关字段
│ 例:调度(pid → next_pid)
│
├── 资源指针 → key=ptr/address
│ 例:内存分配(kmalloc.ptr → kfree.ptr)
│
└── 请求标识 → key=request_id/bio
例:I/O请求(提交 → 完成)
注意:
rundelay不需要设置key属性,内部会自动设置syscalls不需要设置key属性,内部会自动设置常用属性速查: | 属性 | 用途 | 适用分析器 | |-----|------|-----------| | stack | 启用调用栈 | 所有支持堆栈的分析器 | | alias=str | 事件别名 | top, multi-trace, sql | | key=EXPR | 关联键 | multi-trace, top | | top-by=EXPR | 排序字段 | top | | ptr=EXPR | 指针字段 | kmemleak | | size=EXPR | 大小字段 | kmemleak, kmemprof | | batch=N | 每N个事件立即处理 | 需要实时处理事件时使用 |
完整属性列表参考 事件属性。
通用选项参数:
-m, --mmap-pages # perf ringbuffer大小(页数)
-i, --interval <ms> # 输出间隔
-C, --cpus # 监控指定的cpu
-p, --pids # 监控指定的进程
-o, --output <file> # 把stdout/stderr重定向到文件
--watermark <0-100> # 唤醒perf-prof的水位,设置可降低工具自身的cpu消耗
--perins # 按每个实例独立输出统计结果(见"--perins:按实例统计"小节)
根据分析器类型选择执行流程:
延迟分析采用渐进式分析,从统计概览逐步深入到细节:
步骤1:基础统计(了解延迟分布)
# 先执行基础统计,周期性输出延迟分布
perf-prof <profiler> [事件选项] -i 1000 --order
# 示例:系统调用延迟统计
perf-prof syscalls -e raw_syscalls:sys_enter -e raw_syscalls:sys_exit -i 1000
# 示例:调度延迟统计
perf-prof rundelay -e sched:sched_wakeup*,sched:sched_switch -e sched:sched_switch -p <pid> -i 1000
# 示例:块设备IO延迟统计
perf-prof blktrace -d /dev/sda -i 1000
解读输出:关注延迟分布(min/avg/max)、P99等百分位数,确定异常阈值。重点关注max等大的延迟毛刺。
阈值设置原则:
步骤2:阈值过滤(聚焦异常事件)
# 根据步骤1的统计结果,设置--than参数过滤超过阈值的事件,避免设置的阈值过小造成大量输出。
perf-prof <profiler> [事件选项] -i 1000 --order --than <threshold>
解读输出:统计异常事件数量和分布,确认问题严重程度。
步骤3:细节跟踪(定位根因)
# 加上--detail参数,筛选并输出异常事件范围内的中间事件
perf-prof <profiler> [事件选项] -i 1000 --order --than <threshold> --detail=<samecpu>
解读输出:分析每个异常事件的时间戳、进程、堆栈等信息,定位根因。
步骤4:丰富细节(定位根因)
# 针对multi-trace、syscalls、rundelay:加上untraced事件,打开堆栈,还原延迟范围内的中间细节
perf-prof <profiler> -e <event> -e <event,event//untraced/stack/> -i 1000 --order --than <threshold> --detail=<samecpu>
解读输出:分析延迟范围的中间细节,定位根因。
# 直接执行,周期性输出统计结果
perf-prof <profiler> [事件选项] -i 1000 [其他选项]
分析输出:
├── 问题定位清晰 → 完成分析
├── 出现事件丢失(stderr出现:lost xx events on) → 调整-m参数增加ringbuffer,或使用-o输出到文件避免终端瓶颈,重新执行
├── 延迟分析需要深入 → 按6.1流程逐步添加--than和--detail参数
├── 需要更细粒度 → 调整选项参数/过滤器/阈值,重新执行
├── 输出量太大 → 立即结束命令,调整选项参数/增加过滤器/调大阈值,重新执行
├── 需要不同视角 → 返回第二步,选择其他分析器
| └── 分析延迟根因 → multi-trace
└── 需要关联分析 → 使用multi-trace进行联合分析
选项参数分为三类:
-h 查看以下记录几个关键通用选项的使用技巧。
--watermark <0-100> 控制内核何时唤醒 perf-prof 读取 ringbuffer。值为 ringbuffer 大小的百分比,写满该比例时唤醒用户态。
核心权衡:实时性 vs CPU开销
| 值 | 行为 | 适用场景 | |----|------|----------| | 0 | 每个事件立即唤醒 | 需要实时处理事件的场景 | | 1-25 | 低水位,较快唤醒 | 对时效有一定要求 | | 50(默认附近) | 平衡 | 一般统计分析 | | 75-100 | 高水位,批量唤醒 | 高频事件聚合统计,降低 perf-prof 自身 CPU 消耗 |
什么场景需要实时处理事件(--watermark 0):
/proc/<pid>/cmdline、/proc/<pid>/status),进程可能随时退出什么场景不需要实时处理:
与 batch=N 事件属性的关系:
--watermark 是全局选项,对所有事件生效,按 ringbuffer 字节量控制唤醒batch=N 是 per-event 属性,按事件个数控制唤醒(如 batch=1 表示每个事件立即处理)batch=N,该事件不受 --watermark 控制,独立按事件计数唤醒--watermark 降低开销,个别需要实时处理的事件用 batch=1--order 启用基于时间戳的事件排序。多 CPU 系统上,不同 CPU 的 ringbuffer 独立投递,事件到达用户态可能乱序。启用排序会引入一定的性能开销,非必要不使用。
排序原理: --order 不引入额外的缓冲区,而是直接在各 CPU 的 ringbuffer 上做堆排序。当某个 ringbuffer 被唤醒时,以该 ringbuffer 最新事件的时间戳作为排序边界,将所有 ringbuffer 中早于该时间的事件按序投递给分析器。因此排序的时效性取决于 --watermark 的配置——水位越低,排序边界推进越快。
何时需要 --order:
排序的核心判断依据:事件是否需要时序分析,且可能来自不同的 ringbuffer(实例)。
| 场景 | 是否需要 | 原因 | |------|---------|------| | 事件需要时序分析,跨多实例 | 必须 | 不同 ringbuffer 投递可能乱序 | | 事件需要时序分析,单实例(-C 0 或 -t tid) | 不需要 | 单 ringbuffer,天然有序 | | 事件相互独立,用于计数/聚合/统计 | 不需要 | 不依赖事件顺序 |
判断流程:
问:事件是否需要时序分析(延迟配对、因果顺序、按时间打印)?
│
├── 否 → 不需要 --order
│ 例:计数、聚合、独立事件统计
│
└── 是 → 问:事件是否可能来自不同的 ringbuffer(多实例)?
│
├── 否(单实例:-C 0、-t tid) → 不需要 --order
│
└── 是(多 CPU 或多线程) → 需要 --order
原则: blktrace、kvmmmu、task-state 默认启用排序,无需手动指定。
-m <pages> 设置 perf ringbuffer 大小,单位为页(4KB/页)。值必须为 2 的幂次方。
注意: 这是每个实例分配的页数。实例由 -C(CPU)或 -p/-t(进程/线程)决定(详见"--perins:按实例统计")。总内存消耗 = 实例数 × -m × 4KB。
核心权衡:perf-prof 自身内存消耗 vs 事件丢失
| 值 | 内存/实例 | 适用场景 | |----|----------|----------| | 1 | 4KB | 极低频事件,节省内存 | | 8 | 32KB | 低频事件(每秒几十个) | | 32 | 128KB | 一般场景 | | 128 | 512KB | 高频事件(每秒数千个) | | 256+ | 1MB+ | 突发大量事件、带堆栈的事件 |
调整原则:
当 stderr 出现事件丢失警告时,需要增大 -m 值:
profiler: lost N events (total)profiler: lost N events on CPU #X 或 profiler: lost N events on thread #X应对事件丢失的手段:
-m 值(翻倍尝试:32 → 64 → 128)-o 输出到文件,避免终端成为瓶颈--watermark 加速消费--perins 是 "per instance" 的缩写,启用后会显示每个实例的独立统计结果。
实例的含义: 由 -C(CPU)或 -p/-t(进程/线程)决定:
-C 0-3),每个 CPU 是一个实例,显示每个 CPU 的统计-p/-t),每个线程是一个实例,显示每个线程的统计默认行为: 不指定 --perins 时,所有实例的数据汇总为一个统计结果输出。
适用场景:
EVENT,EVENT,...
EVENT: sys:name[/filter/ATTR/ATTR/.../]
profiler[/option/ATTR/ATTR/.../]
kprobe:func[/filter/ATTR/ATTR/.../]
kretprobe:func[/filter/ATTR/ATTR/.../]
uprobe:func@"file"[/filter/ATTR/ATTR/.../]
uretprobe:func@"file"[/filter/ATTR/ATTR/.../]
filter: trace events filter
==, !=, <, <=, >, >=, &==, !=, ~(通配符)&&, ||, ()stack - 为指定的事件打开堆栈max-stack=int - 指定堆栈的深度alias=str - 事件别名,只用于hrcount, hrtimer, multi-trace, num-dist, top, sqlbatch=N - 每批处理N个事件,N=1表示每个事件立即处理,默认使用watermark策略。用于需要实时处理事件的场景(如读取短命进程的/proc信息)cpus=cpu[-cpu] - 指定事件Attach到单独的cpu列表,与-C, --cpus指定的cpu列表取交集top-by=EXPR - 增加top显示字段,参与输出排序,只用于toptop-add=EXPR - 增加top显示字段,不用于输出排序,只用于topcomm=EXPR - 计算显示的进程名,只用于topptr=EXPR - 计算内存分配返回的指针,用于内存分配事件,只用于kmemleaksize=EXPR - 计算内存分配的字节,用于内存分配事件,只用于kmemleak, kmemprofnum=EXPR - 计算分析数值分布的数值字段,只用于num-distkey=EXPR - 设置关联键字段,只用于multi-trace, topprintkey=EXPR - 打印key值,使用'key'作为变量,只用于multi-trace, top(如:printkey=printf("%d",key))role=EXPR - 计算事件的角色,延迟关系中作为起始事件还是结束事件,Bit0置位作为起始事件,Bit1置位作为结束事件,同时置位作为中间事件,只用于multi-tracevm=uuid - 指定事件来着某个虚拟机,通过uuid指定,只用于事件传播push= - 指定事件广播的位置,只用于事件传播。[IP:]PORT指定事件广播的服务端,chardev事件写到字符设备(如:/push="/dev/virtio-ports/g.|qemu.perf0"/),file事件写入文件pull= - 指定事件接受的位置,只用于事件传播。[IP:]PORT指定接收事件的服务端,chardev接收事件的字符设备,file接收事件的文件index=field - 指定 SQL的索引字段,只用于 sqlEXPR - 计算表达式,使用事件的字段作为变量,在用户态计算。执行perf-prof expr -h获得帮助perf-prof <profiler> -h查看帮助kprobe_events.md或uprobe_events.md详细的分析器文档在 references/ 目录:
development
Maintainer-only workflow for handling GitHub Secret Scanning alerts on OpenClaw. Use when Codex needs to triage, redact, clean up, and resolve secret leakage found in issue comments, issue bodies, PR comments, or other GitHub content.
development
Maintainer workflow for OpenClaw releases, prereleases, changelog release notes, and publish validation. Use when Codex needs to prepare or verify stable or beta release steps, align version naming, assemble release notes, check release auth requirements, or validate publish-time commands and artifacts.
development
Run, watch, debug, and extend OpenClaw QA testing with qa-lab and qa-channel. Use when Codex needs to execute the repo-backed QA suite, inspect live QA artifacts, debug failing scenarios, add new QA scenarios, or explain the OpenClaw QA workflow. Prefer the live OpenAI lane with regular openai/gpt-5.4 in fast mode; do not use gpt-5.4-pro or gpt-5.4-mini unless the user explicitly overrides that policy.
development
End-to-end Parallels smoke, upgrade, and rerun workflow for OpenClaw across macOS, Windows, and Linux guests. Use when Codex needs to run, rerun, debug, or interpret VM-based install, onboarding, gateway smoke tests, latest-release-to-main upgrade checks, fresh snapshot retests, or optional Discord roundtrip verification under Parallels.