Linux监控&性能调优分析-perf(中)监控应用程序性能及剖析内存访问

在调查系统性能问题时,可以使用 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 列中的高数字表明发生了错误共享,需要进一步检查发生错误共享的高速缓存行,以调试错误共享活动。

声明:文中观点不代表本站立场。本文传送门:https://eyangzhen.com/420710.html

(0)
联系我们
联系我们
分享本页
返回顶部