Appearance
perf lock —— 锁竞争分析
更新时间:2026-08-06
perf lock 追踪内核锁事件(mutex、spinlock、rwsem 等),分析锁竞争问题——回答"哪个锁被争得最凶、谁在等锁、等了多久"。
关联:perf-c2c.md(缓存争用)、perf-sched.md(调度延迟)、锁争用演示
一、perf lock 能回答什么问题
| 问题 | 子命令 |
|---|---|
| 哪些锁竞争最严重? | perf lock report |
| 每个锁的等待时间? | perf lock report 的 wait time |
| 谁持有锁最久? | perf lock report 的 hold time |
| 锁竞争的完整时间线? | perf lock script |
| 锁是 spinlock 还是 mutex? | perf lock info |
| 用户态 futex 竞争? | perf lock contention(Linux 5.14+) |
二、基本使用
2.1 录制锁事件
bash
# 录制锁事件(需要 root)
perf lock record ./your_program
# 录制全系统
perf lock record -a -- sleep 30
# 录制时记录调用栈
perf lock record -g ./your_program2.2 分析锁竞争
bash
# 查看锁竞争报告
perf lock report
# 或指定文件
perf lock report -i perf.data2.3 输出解读
bash
Name acquired contended avg wait (ns) total wait (ns) max wait (ns) min wait (ns)
&q->lock 12345 5678 12,345 70,123,456,789 1,234,567 123
&mm->mmap_sem 2345 123 56,789 6,987,654,321 3,456,789 2,345
&rq->lock 5678 89 23,456 2,086,758,964 1,000,000 1,234| 列 | 含义 | 判断 |
|---|---|---|
| Name | 锁的符号名 | 定位到具体锁变量 |
| acquired | 获取锁的总次数 | — |
| contended | 发生竞争的获取次数 | 高 → 热点锁 |
| avg wait (ns) | 平均等待时间 | > 1000ns → 竞争显著 |
| total wait (ns) | 总等待时间 | 贡献最大的锁 |
| max wait (ns) | 最大等待时间 | > 1ms → 长尾延迟 |
| min wait (ns) | 最小等待时间 | — |
2.4 查看锁信息
bash
perf lock info显示录制期间涉及的锁类型和数量。
2.5 锁事件脚本
bash
perf lock script输出每次锁获取/释放/竞争的原始事件流。
三、常用选项
| 选项 | 含义 |
|---|---|
-g | 记录调用栈(看谁在获取锁) |
-i <file> | 指定 perf.data 文件 |
-t | 显示线程级别的锁信息 |
-k <symbol> | 只看指定锁 |
-m | 按锁地址排序 |
-v | 详细输出 |
四、perf lock contention(用户态锁,Linux 5.14+)
bash
# 直接分析用户态锁竞争(不需要先 record)
perf lock contention -a -- sleep 10
# 看调用栈
perf lock contention -a -g -- sleep 10
# 只看用户态 futex
perf lock contention -a -- sleep 10这是新内核的功能,基于 BPF 直接追踪锁竞争,无需两步录制-分析流程。
五、诊断流程

六、实战场景
场景 1:多线程程序吞吐上不去
bash
perf lock record -g -a -- sleep 30
perf lock report如果某个锁 contended / acquired > 50%,说明每次获取几乎都在竞争——这个锁是瓶颈。
场景 2:定位长尾延迟
看 max wait 列。如果某个锁 max wait > 10ms,说明偶尔有线程被卡住很久。
bash
# 同时看调度分析
perf sched latency锁竞争和调度延迟往往同时出现。
场景 3:推断锁类型是否合理
| avg wait | 可能问题 | 建议 |
|---|---|---|
| < 100ns | 几乎无竞争 | — |
| 100ns - 1μs | 轻微竞争 | 可接受 |
| 1μs - 10μs | 明显竞争 | 考虑缩短临界区 |
| > 10μs | 严重竞争 | 考虑换锁类型/无锁方案 |
七、perf lock vs 其他工具
| 工具 | 分析对象 | 优点 |
|---|---|---|
| perf lock | 内核锁(mutex/spinlock/rwsem) | 开销低,直接给定量数据 |
| perf lock contention | 用户态锁(futex/mutex) | 无需录制的实时分析 |
| perf c2c | 缓存行级别争用 | 对无锁结构的争用也能分析 |
| perf sched latency | 调度延迟 | 锁竞争→调度延迟的后果 |
| strace | syscall 级别 | 看 futex 调用但不给等待时间 |
八、注意事项
- 需要 root:内核锁事件仅 root/cap 可访问。
- 内核态锁:
perf lock record追踪的是内核态的锁事件。用户态 pthread_mutex 通过 futex 进入内核后也会被追踪。 - 数据量:高竞争场景下锁事件极密,
perf.data可能很大。控制录制时间 ≤ 30s。 - 新内核推荐
perf lock contention:不需要两步流程,开销更低,且支持调用栈。
九、与相关文档的交叉引用
| 场景 | 文档 |
|---|---|
| 缓存争用(可能伴随锁竞争) | perf-c2c.md |
| 锁竞争导致的调度延迟 | perf-sched.md |
| 多线程 IO 三步分析法 | perf-multithread-io-analysis.md |
| 锁争用动手实验 | 锁争用演示 |
十、一句话总结
perf lock是锁竞争的"照妖镜"——精准量化每个锁的获取次数、竞争比例和等待时间,让你一眼看出多线程程序的"排队瓶颈"是哪个锁、等了多久、值不值得优化。