5 用perf调查繁忙的CPU
在调查系统性能问题时,可以使用 perf 工具来识别和监控最繁忙的 CPU,以便集中精力。
5.1 用 perf stat显示哪些CPU事件被计数
通过禁用 CPU 计数聚合,您可以使用 perf stat 显示哪些CPU事件被计数。要使用此功能,必须使用 -a 标志在全系统模式下统计事件。
# perf stat -a -A sleep seconds
上例显示了一组默认的常见硬件和软件事件的计数,记录的时间段为秒,由使用 sleep 命令决定,从 CPU0 开始,按升序对每个 CPU 进行计数。因此,指定诸如周期之类的事件可能很有用:
# perf stat -a -A -e cycles sleep seconds
5.2 用 perf report 显示对哪些 CPU 进行了采样
perf record 命令对性能数据进行采样,并将这些数据存储在 perf.data 文件中,可以用 perf report 命令读取。perf record 命令总是记录采样的 CPU。您可以配置 perf report 来显示这些信息。
# perf report --sort cpu
Samples: 3K of event 'cycles', Event count (approx.): 9176209572
Children Self CPU
+ 8.87% 8.87% 006 ◆
+ 5.06% 5.06% 033 ▒
+ 4.80% 4.80% 041 ▒
+ 4.48% 4.48% 034
...
您可以按 CPU 和命令排序,以显示有关 CPU 时间使用情况的更详细信息:
# perf report --sort cpu,comm
Samples: 3K of event 'cycles', Event count (approx.): 9176209572
Children Self CPU Command
+ 8.20% 8.20% 006 erl_child_setup
+ 4.37% 4.37% 041 gunicorn
+ 3.71% 3.71% 034 gunicorn
+ 3.37% 3.37% 033 java-perf-backe
+ 2.56% 2.56% 039 gunicorn
+ 2.43% 2.43% 038 gunicorn
...
5.3 使用 perf top在剖析过程中显示特定 CPU
您可以配置 perf top,以便在实时剖析系统时显示特定 CPU 及其相对使用情况。
# perf top --sort cpu
Samples: 10K of event 'cycles', 4000 Hz, Event count (approx.): 2139900109 lost: 0/0 drop: 0/0
Overhead CPU
36.67% 096
3.45% 032
...
此示例将实时按开销使用情况降序列出 CPU 及其各自的开销。
您可以按 CPU 和命令排序,以获得更详细的 CPU 时间使用情况信息:
# perf top --sort cpu,comm
Samples: 11K of event 'cycles', 4000 Hz, Event count (approx.): 3705425468 lost: 0/0 drop: 0/0
Overhead CPU Command
21.67% 115 perf
15.61% 018 erl_child_setup
...
此示例将按总开销从大到小排列命令,并识别实时执行命令的 CPU。
5.4. 使用 perf record 和 perf report 监控特定 CPU
您可以配置 perf record,使其仅对感兴趣的特定 CPU 进行采样,并使用 perf report 分析生成的 perf.data 文件,以进行进一步分析。
# perf record -C 0-6 sleep 10
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.812 MB perf.data (656 samples) ]
# perf report
Samples: 656 of event 'cycles', Event count (approx.): 145210980
Overhead Command Shared Object Symbol
10.53% swapper [kernel.kallsyms] [k] arch_local_irq_enable
5.78% 1_scheduler beam.smp [.] sched_spin_wait
4.73% swapper [kernel.kallsyms] [k] _nohz_idle_balance.constprop.0.isra.0
4.56% 1_scheduler [kernel.kallsyms] [k] arch_local_irq_enable
3.99% swapper [kernel.kallsyms] [k] arch_cpu_idle
3.75% 1_scheduler [kernel.kallsyms] [k] arch_local_irq_restore
3.35% 1_scheduler [kernel.kallsyms] [k] futex_wake
1.98% 2_scheduler beam.smp [.] sched_spin_wait
1.90% 1_scheduler beam.smp [.] process_main
1.88% 7_scheduler beam.smp [.] sched_spin_wait
1.82% swapper [kernel.kallsyms] [k] update_sg_lb_stats
1.81% 6_scheduler beam.smp [.] sched_spin_wait
1.56% swapper [kernel.kallsyms] [k] update_blocked_averages
...
6 使用perf监控应用程序性能
您可以使用 perf 工具监控和分析应用程序性能。
6.1 将 perf record附加到运行中的进程
您可以将perf record附加到正在运行的进程。这将指示perf record仅在指定进程中采样和记录性能数据。
perf record -p ID1,ID2 sleep seconds
上例通过使用 sleep 命令,采样并记录了进程 ID 为 ID1 和 ID2 的进程的性能数据,时间段为秒。您还可以配置 perf 记录特定线程中的事件:
$ perf record -t ID1,ID2 sleep seconds
注意:使用 -t 标志并指定线程 ID 时,perf 默认会禁用继承。您可以通过添加 --inherit 选项来启用继承。
6.2 使用perf record捕捉调用图数据
您可以配置 perf record 工具,使其记录哪个函数正在调用性能配置文件中的其他函数。这有助于在多个进程调用同一函数时识别瓶颈。
$ perf record --call-graph method command
6.3 使用perf report 分析perf.data
# perf report
Samples: 656 of event 'cycles', Event count (approx.): 145210980
Overhead Command Shared Object Symbol
10.53% swapper [kernel.kallsyms] [k] arch_local_irq_enable
5.78% 1_scheduler beam.smp [.] sched_spin_wait
4.73% swapper [kernel.kallsyms] [k] _nohz_idle_balance.constprop.0.isra.0
4.56% 1_scheduler [kernel.kallsyms] [k] arch_local_irq_enable
3.99% swapper [kernel.kallsyms] [k] arch_cpu_idle
...
7 使用 perf 创建 uprobes
uprobe 是 Linux perf工具集中的一个强大功能,它允许我们对正在运行的进程中的用户态函数进行动态追踪。这对于深入了解应用程序的行为、定位性能瓶颈以及调试问题非常有用。
参见: https://mp.weixin.qq.com/s/HAwfHcfOsWLQc6PYbkECVQ
8 使用 perf mem 剖析内存访问
8.1 perf mem 的目的
perf 工具的 mem 子命令可对内存访问(加载和存储)进行采样。perf mem 命令可提供有关内存延迟、内存访问类型、导致高速缓存命中和未命中的函数的信息,并通过记录数据符号提供发生这些命中和未命中的内存位置。
8.2 使用 perf mem 采样内存访问
该命令使用与 perf record 和 perf report 相同的选项,以及一些 mem 子命令独有的选项。记录的数据将保存在当前目录下的 perf.data 文件中,供以后分析之用。
对内存访问进行采样:
# perf mem record -a sleep seconds # 比如 perf mem record -a sleep 10
此示例按照 sleep 命令的规定,在几秒钟内对所有 CPU 的内存访问进行采样。您可以用任何想要采样内存访问数据的命令替换 sleep 命令。默认情况下,perf mem 会对内存加载和存储进行采样。使-用 t 选项并在 perf mem 和 record 之间指定 “加载 ”或 “存储”,可以只选择一种内存操作。对于加载,会捕获内存层次结构级别、TLB 内存访问、总线侦查和内存锁的信息。
打开 perf.data 文件进行分析:
# perf mem report
Available samples
35k cpu/mem-loads,ldlat=30/P
54k cpu/mem-stores/P
cpu/mem-loads,ldlat=30/P 行表示通过内存加载收集的数据,cpu/mem-stores/P 行表示通过内存存储收集的数据。选择感兴趣的类别,按 Enter 键查看数据:
Samples: 35K of event 'cpu/mem-loads,ldlat=30/P', Event count (approx.): 4067062
Overhead Samples Local Weight Memory access Symbol Shared Object Data Symbol Data Object Snoop TLB access Locked
0.07% 29 98 L1 or L1 hit [.] 0x000000000000a255 libspeexdsp.so.1.5.0 [.] 0x00007f697a3cd0f0 anon None L1 or L2 hit No
0.06% 26 97 L1 or L1 hit [.] 0x000000000000a255 ...
此外,在显示数据时,还可以对结果进行排序,以研究不同的兴趣点。例如,按采样期间发生的内存访问类型对内存负载数据进行排序,按所占开销从大到小排序:
# perf mem -t load report --sort=mem
Samples: 35K of event 'cpu/mem-loads,ldlat=30/P', Event count (approx.): 40670
Overhead Samples Memory access
31.53% 9725 LFB or LFB hit
29.70% 12201 L1 or L1 hit
23.03% 9725 L3 or L3 hit
12.91% 2316 Local RAM or RAM hit
2.37% 743 L2 or L2 hit
...
8.3 解释 perf 内存报告输出
不带任何修改器运行 perf mem report 命令后显示的表格将数据分成几列:
- 开销(Overhead)列
表示在该特定功能中收集的全部样本的百分比。
- 样本(Samples)列
显示该行所占的样本数。
-
本地权重(Local Weight)列
显示以处理器内核周期为单位的访问延迟。 -
内存访问(Memory Access)列
显示发生的内存访问类型。
- 符号(Symbol)列
显示函数名称或符号。
-
共享对象(Shared Object)列
显示样本所在 ELF 映像的名称(样本来自内核时使用 [kernel.kallsyms])。 -
数据符号(Data Symbol)列
显示行目标内存位置的地址。通常情况下,由于内存的动态分配或堆栈内存被访问,“数据符号 ”列会显示原始地址。 -
窥探(Snoop)列
显示总线事务。 -
TLB访问(TLB Access)列
显示 TLB 内存访问。 -
锁定(Locked)列
表示函数是否锁定内存。
在默认模式下,函数按降序排序,开销最大的函数显示在最前面。
9 检测假共享
在 SMP 系统中,多个处理器共享同一块物理内存。当多个处理器同时访问同一缓存行(cache line)中的不同数据时,即使这些数据是属于不同变量的,也会导致缓存一致性协议频繁地进行无效化和刷新操作,从而降低系统性能。这种现象被称为假共享。
假共享的原因:
- 缓存行: 缓存系统以缓存行为单位进行数据传输。如果多个变量恰好位于同一个缓存行中,即使它们之间没有逻辑关系,也会被一起加载和存储。
- 缓存一致性协议: 为了保证多个处理器之间的数据一致性,缓存一致性协议会检测到缓存行的修改,并强制其他缓存中的对应缓存行失效。
- 竞争: 当多个处理器同时修改同一个缓存行中的不同数据时,就会导致频繁的缓存行无效化和刷新操作,增加系统总线流量,降低系统性能。
假共享对系统性能的影响
- 性能下降: 频繁的缓存一致性操作会增加系统总线流量,导致处理器缓存命中率降低,从而影响系统整体性能。
- 可扩展性受限: 随着处理器数量的增加,假共享问题会变得更加严重,限制了系统的可扩展性。
如何避免假共享?
- 数据对齐: 将不同变量对齐到不同的缓存行上,避免它们共享同一个缓存行。
- 填充: 在变量之间插入填充字节,增加变量之间的距离,使其不至于落在同一个缓存行中。
- 伪共享变量: 引入伪共享变量,将多个变量与伪共享变量放在同一个缓存行中,从而避免它们与其他重要的变量共享缓存行。
- 缓存行大小: 了解缓存行的大小,并根据缓存行大小来安排数据布局。
- 编译器优化: 利用编译器的优化选项,例如数据对齐选项,来减少假共享的影响。
- 锁粒度: 如果多个线程需要访问共享数据,可以考虑使用更细粒度的锁,以减少锁竞争。
参考资料
- 软件测试精品书籍文档下载持续更新 https://github.com/china-testing/python-testing-examples 请点赞,谢谢!
- 本文涉及的python测试开发库 谢谢点赞! https://github.com/china-testing/python_cn_resouce
- python精品书籍下载 https://github.com/china-testing/python_cn_resouce/blob/main/python_good_books.md
- Linux精品书籍下载 https://www.cnblogs.com/testing-/p/17438558.html
- 如需技术支持联系钉ding或微信pythontesting , 邮箱: xurongzhong#126.com
9.1 perf c2c的目的
perf 工具的 c2c 子命令可用于共享数据缓存到缓存(C2C)分析。您可以使用 perf c2c 命令检查高速缓存行争用,以检测真假共享。
当对称多处理(SMP)系统中的处理器内核修改同一高速缓存行上的数据项时,其他处理器也在使用该高速缓存行,这时就会发生高速缓存行竞争。这时,使用该高速缓存行的所有其他处理器都必须使其副本失效,并请求更新副本。这会导致性能下降。
perf c2c 命令提供以下信息:
- 检测到竞争的高速缓存行
- 读写数据的进程
- 导致争用的指令
- 发生争执的非统一内存访问 (NUMA) 节点
9.2. 使用 perf c2c 检测高速缓存行竞争
perf c2c 命令支持与 perf record 相同的选项,以及 c2c 子命令独有的一些选项。记录的数据将保存在当前目录下的 perf.data 文件中,以供日后分析。
# perf c2c record -a sleep seconds # 比如# sudo perf c2c record -a sleep 5
此示例按照 sleep 命令的指示,在几秒钟内采样并记录所有 CPU 的缓存行竞争数据。您可以用任何想要收集缓存行竞争数据的命令来替换 sleep 命令。
9.3. 可视化用perf c2c记录的perf.data文件
# perf c2c report --stdio
Total Shared Cache Lines : 55
Load HITs on shared lines : 55454
Fill Buffer Hits on shared lines : 10635
L1D hits on shared lines : 16415
L2D hits on shared lines : 0
LLC hits on shared lines : 8501
Locked Access on shared lines : 14351
Store HITs on shared lines : 109953
Store L1D hits on shared lines : 109449
Total Merged records : 126112
=================================================
c2c details
=================================================
Events : cpu/mem-loads,ldlat=30/P
: cpu/mem-stores/P
Cachelines sort on : Remote HITMs
Cacheline data groupping : offset,pid,iaddr
=================================================
Shared Data Cache Line Table
=================================================
#
# Total Rmt ----- LLC Load Hitm ----- ---- Store Reference ---- --- Load Dram ---- LLC Total ----- Core Load Hit ----- -- LLC Load Hit --
# Index Cacheline records Hitm Total Lcl Rmt Total L1Hit L1Miss Lcl Rmt Ld Miss Loads FB L1 L2 Llc Rmt
# ..... .................. ....... ....... ....... ....... ....... ....... ....... ....... ........ ........ ....... ....... ....... ....... ....... ........ ........
#
0 0x602180 149904 77.09% 12103 2269 9834 109504 109036 468 727 2657 13747 40400 5355 16154 0 2875 529
1 0x602100 12128 22.20% 3951 1119 2832 0 0 0 65 200 3749 12128 5096 108 0 2056 652
2 0xffff883ffb6a7e80 260 0.09% 15 3 12 161 161 0 1 1 15 99 25 50 0 6 1
3 0xffffffff81aec000 157 0.07% 9 0 9 1 0 1 0 7 20 156 50 59 0 27 4
4 0xffffffff81e3f540 179 0.06% 9 1 8 117 97 20 0 10 25 62 11 1 0 24 7
=================================================
Shared Cache Line Distribution Pareto
=================================================
#
# ----- HITM ----- -- Store Refs -- Data address ---------- cycles ---------- cpu Shared
# Num Rmt Lcl L1 Hit L1 Miss Offset Pid Code address rmt hitm lcl hitm load cnt Symbol Object Source:Line Node{cpu list}
# ..... ....... ....... ....... ....... .................. ....... .................. ........ ........ ........ ........ ................... .................... ........................... ....
#
-------------------------------------------------------------
0 9834 2269 109036 468 0x602180
-------------------------------------------------------------
65.51% 55.88% 75.20% 0.00% 0x0 14604 0x400b4f 27161 26039 26017 9 [.] read_write_func no_false_sharing.exe false_sharing_example.c:144 0{0-1,4} 1{24-25,120} 2{48,54} 3{169}
0.41% 0.35% 0.00% 0.00% 0x0 14604 0x400b56 18088 12601 26671 9 [.] read_write_func no_false_sharing.exe false_sharing_example.c:145 0{0-1,4} 1{24-25,120} 2{48,54} 3{169}
0.00% 0.00% 24.80% 100.00% 0x0 14604 0x400b61 0 0 0 9 [.] read_write_func no_false_sharing.exe false_sharing_example.c:145 0{0-1,4} 1{24-25,120} 2{48,54} 3{169}
7.50% 9.92% 0.00% 0.00% 0x20 14604 0x400ba7 2470 1729 1897 2 [.] read_write_func no_false_sharing.exe false_sharing_example.c:154 1{122} 2{144}
17.61% 20.89% 0.00% 0.00% 0x28 14604 0x400bc1 2294 1575 1649 2 [.] read_write_func no_false_sharing.exe false_sharing_example.c:158 2{53} 3{170}
8.97% 12.96% 0.00% 0.00% 0x30 14604 0x400bdb 2325 1897 1828 2 [.] read_write_func no_false_sharing.exe false_sharing_example.c:162 0{96} 3{171}
-------------------------------------------------------------
1 2832 1119 0 0 0x602100
-------------------------------------------------------------
29.13% 36.19% 0.00% 0.00% 0x20 14604 0x400bb3 1964 1230 1788 2 [.] read_write_func no_false_sharing.exe false_sharing_example.c:155 1{122} 2{144}
43.68% 34.41% 0.00% 0.00% 0x28 14604 0x400bcd 2274 1566 1793 2 [.] read_write_func no_false_sharing.exe false_sharing_example.c:159 2{53} 3{170}
27.19% 29.40% 0.00% 0.00% 0x30 14604 0x400be7 2045 1247 2011 2 [.] read_write_func no_false_sharing.exe false_sharing_example.c:163 0{96} 3{171}
9.4 perf c2c 报告输出的解释
- 跟踪事件信息(Trace Events Information)
该表提供 perf c2c record 命令收集的所有加载和存储样本的高级摘要。
- 全局共享缓存行事件信息(Global Shared Cache Line Event Information)
该表提供共享缓存行的统计信息。
-
c2c详情(c2c Details)
该表提供有关采样事件的信息,以及 perf c2c 报告数据在可视化中的组织方式。 -
共享数据高速缓存行表(Shared Data Cache Line Table)
该表提供了检测到错误共享的最热高速缓存行的一行摘要,默认情况下按每个高速缓存行检测到的远程 Hitm 数量降序排序。
- 共享缓存行分布帕累托表(Shared Cache Line Distribution Pareto)
该表提供了有关发生竞争的各高速缓存行的各种信息:
- 缓存行在 NUM 列中编号,从 0 开始。
- 数据地址偏移列中包含每个高速缓存行的虚拟地址,随后是发生不同访问的高速缓存行的偏移量。
- Pid 列包含进程 ID。
- 代码地址列包含指令指针代码地址。
- cycles 标签下的列显示平均加载延迟。
- cpu cnt 列显示样本来自多少个不同的 CPU(即有多少个不同的 CPU 在等待该给定位置的索引数据)。
- 符号列显示函数名称或符号。
- 共享对象(Shared Object)列显示样本所在 ELF 映像的名称(样本来自内核时使用 [kernel.kallsyms])。
- 源文件:行列显示源文件和行号。
- Node{cpu list} 列显示样本来自每个节点的哪些特定 CPU。
9.5. 使用 perf c2c 检测错误共享
# perf c2c report --stdio
...
在 “跟踪事件信息”表中,找到包含 LLC Misses to Remote Cache (HITM) 值的行:
=================================================
Trace Event Information
=================================================
Total records : 329219
Locked Load/Store Operations : 14654
Load Operations : 69679
Loads - uncacheable : 0
Loads - IO : 0
Loads - Miss : 3972
Loads - no mapping : 0
Load Fill Buffer Hit : 11958
Load L1D hit : 17235
Load L2D hit : 21
Load LLC hit : 14219
Load Local HITM : 3402
Load Remote HITM : 12757
Load Remote HIT : 5295
Load Local DRAM : 976
Load Remote DRAM : 3246
Load MESI State Exclusive : 4222
Load MESI State Shared : 0
Load LLC Misses : 22274
LLC Misses to Local DRAM : 4.4%
LLC Misses to Remote DRAM : 14.6%
LLC Misses to Remote cache (HIT) : 23.8%
LLC Misses to Remote cache (HITM) : 57.3%
Store Operations : 259539
Store - uncacheable : 0
Store - no mapping : 11
Store L1D Hit : 256696
Store L1D Miss : 2832
No Page Map Rejects : 2376
Unable to parse data source : 1
LLC Misses to Remote Cache (HITM)行值列中的百分比表示在修改的高速缓存行中跨 NUMA 节点发生的 LLC 缺失的百分比,是发生错误共享的关键指标。
检查共享数据高速缓存行表中 LLC 负载 Hitm 字段的 Rmt 列:
=================================================
Shared Data Cache Line Table
=================================================
#
# Total Rmt ----- LLC Load Hitm ----- ---- Store Reference ---- --- Load Dram ---- LLC Total ----- Core Load Hit ----- -- LLC Load Hit --
# Index Cacheline records Hitm Total Lcl Rmt Total L1Hit L1Miss Lcl Rmt Ld Miss Loads FB L1 L2 Llc Rmt
# ..... .................. ....... ....... ....... ....... ....... ....... ....... ....... ........ ........ ....... ....... ....... ....... ....... ........ ........
#
0 0x602180 149904 77.09% 12103 2269 9834 109504 109036 468 727 2657 13747 40400 5355 16154 0 2875 529
1 0x602100 12128 22.20% 3951 1119 2832 0 0 0 65 200 3749 12128 5096 108 0 2056 652
2 0xffff883ffb6a7e80 260 0.09% 15 3 12 161 161 0 1 1 15 99 25 50 0 6 1
3 0xffffffff81aec000 157 0.07% 9 0 9 1 0 1 0 7 20 156 50 59 0 27 4
4 0xffffffff81e3f540 179 0.06% 9 1 8 117 97 20 0 10 25 62 11 1 0 24 7
该表按每个高速缓存行检测到的远程 Hitm 数量降序排序。LLC Load Hitm 部分 Rmt 列中的高数字表明发生了错误共享,需要进一步检查发生错误共享的高速缓存行,以调试错误共享活动。
标签:Load,缓存,perf,性能,.......,内存,监控,CPU From: https://www.cnblogs.com/testing-/p/18381971