Linux(09)之perf(1)基础知识总结
Author:Onceday Date:2023年1月31日
漫漫长路,才刚刚开始…
参考文档:
-
Tutorial - Perf Wiki (kernel.org)
-
linux性能分析工具专题-perf(事件采样,全面性能分析)_perf annotate_runafterhit的博客-CSDN博客
-
perf(1) - Linux manual page (man7.org)
-
使用perf工具分析程序性能 小竹’s blog
-
perf使用说明 yoc.docs t-head
-
Linux Perf 性能分析工具及火焰图浅析 滴滴云 知乎
-
perf学习总结 高兴广 知乎
-
Linux性能工具有哪些? 人人极客社区 微信公众号
-
Perf:Linux下性能分析工具 0xFE 稀土掘金
文章目录
- Linux(09)之perf(1)基础知识总结
- 1. 概述
- 1.1 Perf背景历史
- 1.2 PMU(性能监控单元)
- 1.3 Perf的原理
- 1.4 Perf性能事件
- 1.5 Perf性能事件的属性
- 2. Perf实际命令
- 2.1 perf命令
- 2.2 perf list 查看支持的性能事件
- 2.3 perf 性能事件修饰符
- 2.4 测量特定硬件上的PMU事件
- 2.5 参数化的性能事件
- 2.6 事件组测量
- 2.7 perf list性能事件分类
1. 概述
这张图是来自Brendan Gregg大佬提供的linux分析工具的应用场景,可以看出几乎包含了系统每个地方应该用什么工具去分析。
这里我们只考虑perf这一种工具,重点在于使用该工具来理解程序在Linux系统上的性能消耗情况。
1.1 Perf背景历史
Perf
全名是Performance Event, 是一个功能强大的性能分析工具,它主要用于测量和分析Linux操作系统中的软件性能。perf
是基于Linux内核的性能监控功能实现的,它可以帮助开发者找到程序的性能瓶颈、优化代码以及提高系统的整体性能。
perf
工具的诞生要追溯到2008年,当时Linux内核社区为了改善内核性能分析的体验,开始开发了一个基于内核的性能监控子系统,即Performance Monitoring Unit(PMU)。随着时间的推移,perf
工具在内核社区的不断贡献和改进下,功能日益完善,逐渐成为Linux平台下必备的性能分析工具。
perf
工具具有广泛的功能作用,包括但不限于:
-
CPU性能监控:
perf
可以收集和报告各种CPU性能事件,如缓存命中率、分支预测错误等,从而帮助开发者了解程序的运行效率。 -
内存性能监控:
perf
可以分析程序的内存访问模式,如内存分配与释放,帮助开发者优化内存使用。 -
系统调用追踪:
perf
可以追踪程序的系统调用,帮助开发者发现潜在的性能问题。 -
热点函数分析:通过采样程序执行过程中的函数调用,
perf
可以找到程序中执行时间最长的函数,为开发者提供优化方向。 -
硬件事件统计:
perf
还可以统计硬件事件,如CPU缓存、分支预测等,以评估程序的硬件利用效率。
perf
工具自2008年诞生以来,经历了多次重要的更新:
-
2.6.31内核:
perf
初始版本发布,支持基本的性能监控功能。 -
2.6.35内核:引入了
perf trace
命令,支持系统调用追踪。 -
3.0内核:支持动态追踪技术,提高了
perf
的灵活性。 -
4.1内核:引入了
perf c2c
命令,支持缓存行级别的分析。
随着Linux内核的不断升级,perf
工具也在不断地扩展和完善其功能,以满足更多性能分析的需求。
虽然perf
是为Linux操作系统设计的,但它也可以在其他类Unix系统上运行,如FreeBSD、macOS等。然而,由于这些平台的内核实现和硬件架构差异,perf
在不同平台上的功能和性能可能会有所差异。因此,在使用perf
进行性能分析时,需要考虑到目标平台的特点和限制。
1.2 PMU(性能监控单元)
PMU(Performance Monitoring Unit,性能监视单元)是现代 CPU 中的一个重要部件,它用于监控和收集与处理器性能相关的硬件事件。PMU 可以帮助开发人员了解程序在特定处理器上的运行情况,从而进行针对性的优化。
PMU 通常由多个硬件性能计数器(Hardware Performance Counter,HPC)组成。这些计数器用于统计特定硬件事件发生的次数,例如:
- CPU 周期(Cycles)
- 指令数(Instructions)
- 缓存命中/未命中(Cache Hits/Misses)
- 分支预测成功/失败(Branch Predictions Correct/Incorrect)
在使用 PMU 进行性能分析时,需要选择要监控的事件。然后,PMU 会将事件发生的次数记录在对应的性能计数器中。通过收集和分析这些数据,可以找出程序的瓶颈。
在 Linux 系统下,Perf 工具可以访问 PMU 并利用其提供的性能数据。Perf 提供了多种命令和选项来配置和分析 PMU 数据。在前面的 Perf 教程中,我们已经讨论了如何使用 Perf 进行性能分析。
需要注意的是,不同处理器的 PMU 可能会有所不同,支持的事件种类和性能计数器数量也可能有差异。不过,Perf 工具已经对大部分流行的处理器进行了抽象,使得在多种处理器上都能使用统一的接口来进行性能分析。
1.3 Perf的原理
- perf学习总结 - 知乎 (zhihu.com)
perf功能强大:它可以测量CPU性能计数器、跟踪点、kprobes和uprobes(动态跟踪)。它能够进行轻量级剖析。它也包含在Linux内核的tools/perf下,并经常更新和增强。
perf开始时是一个用于在Linux中使用性能计数器子系统的工具,并经过了各种增强以添加跟踪功能。性能计数器是CPU硬件寄存器,对硬件事件进行计数,例如执行的指令、缓存未命中或分支预测错误。它们构成了分析应用程序以跟踪动态控制流和识别热点的基础。Perf为特定于硬件的功能提供了丰富的通用抽象。其中,它提供了每个任务、每个CPU和每个工作负载的计数器,并在这些计数器和源代码事件注释的基础上进行采样。
**跟踪点(tracepoints)**是位于代码中逻辑位置的插桩点,例如系统调用、TCP/IP事件、文件系统操作等。在不使用时,它们的开销可以忽略不计,并且可以通过perf命令启用,以收集包括时间戳和堆栈跟踪在内的信息。Perf还可以使用kprobes和uprobes框架动态创建跟踪点,用于内核和用户空间的动态跟踪。它们的可能性是无限的。
-
kprobes
(Kernel Probes)是一种用于追踪内核代码执行的动态追踪技术。通过在内核中插入kprobes
,开发者可以监控内核函数的调用和返回,收集关键事件的信息,如参数值、返回值等。kprobes
的工作原理是基于内核的断点机制。在插入kprobes
时,内核会在目标地址处插入一个断点指令。当程序执行到该指令时,内核会触发一个异常,并将控制权转交给kprobes
的处理函数。处理函数可以访问当前的CPU寄存器和内存,获取事件信息。执行完处理函数后,程序会继续从目标地址处执行。kprobes
的优势在于,它可以在运行时动态地追踪内核代码,而无需修改或重新编译内核。此外,kprobes
对系统性能的影响较小,因为它只在关键事件发生时触发。 -
uprobes
(User Probes)是一种用于追踪用户空间代码执行的动态追踪技术。与kprobes
类似,uprobes
也可以在运行时插入探针,监控用户程序的函数调用和返回。uprobes
的工作原理与kprobes
相似,也是基于断点机制。不同之处在于,uprobes
插入的断点位于用户空间代码中,因此需要内核与用户空间的协同处理。当用户程序执行到断点时,内核会触发一个异常,将控制权转交给uprobes
的处理函数。处理函数可以访问当前的CPU寄存器和内存,获取事件信息。执行完处理函数后,程序会继续从目标地址处执行。uprobes
的优势在于,它可以在运行时动态地追踪用户空间代码,而无需修改或重新编译程序。类似于kprobes
,uprobes
对系统性能的影响也较小。
Perf有两种工作模式:
- 计数模式(Couting Mode),Counting Mode 将会精确统计一段时间内 CPU 相关硬件计数器数值的变化。为了统计用户感兴趣的事件,Perf Tool 将设置性能控制相关的寄存器。这些寄存器的值将在监控周期结束后被读出。
- 采样模式(Sampling Mode),Sampling Mode 将以定期采样方式获取性能数据。PMU 计数器将为某些特定事件配置溢出周期。当计数器溢出时,相关数据,如 IP、通用寄存器、EFLAG 将会被捕捉到。
1.4 Perf性能事件
Perf事件大概分成以下几个类别:
- 硬件事件 (Hardware Events): 这些事件是由处理器硬件本身产生的。例如:
- instructions: 已执行的指令数
- cycles: 处理器周期数
- cache-references: 缓存引用次数
- cache-misses: 缓存未命中次数
- branch-instructions: 分支指令数
- branch-misses: 错误预测的分支指令数
- 硬件缓存事件 (Hardware Cache Events): 这些事件与处理器的缓存相关,例如:
L1-dcache-loads
: L1 数据缓存加载次数L1-dcache-load-misses
: L1 数据缓存加载未命中次数L1-dcache-stores
: L1 数据缓存存储次数L1-dcache-store-misses
: L1 数据缓存存储未命中次数L1-dcache-prefetches
: L1 数据缓存预取次数L1-dcache-prefetch-misses
: L1 数据缓存预取未命中次数
- 软件事件 (Software Events): 这些事件是由操作系统产生的,例如:
context-switches
: 上下文切换次数cpu-migrations
: CPU 迁移次数page-faults
: 页错误次数minor-faults
: 次要页错误次数major-faults
: 主要页错误次数
- 跟踪点事件 (Tracepoint Events): 这些事件是由内核中的跟踪点生成的,可以通过
perf list
命令获取完整的跟踪点事件列表。跟踪点事件可以用于监控诸如调度器行为、内存管理等内核子系统的性能。 - 调查事件(Probe events): 用户自定义的事件, 动态插入到内核之中。
1.5 Perf性能事件的属性
以下原文请参考perf学习总结 - 知乎 (zhihu.com)。
硬件性能事件由处理器中的PMU提供支持。由于现代处理器的主频非常高,再加上深度流水线机制,从性能事件被触发,到处理器响应 PMI中断,流水线上可能已处理过数百条指令。那么PMI中断采到的指令地址就不再是触发性能事件的那条指令的地址了,而且可能具有非常严重的偏差。为了解决这个问题,Intel处理器通过PEBS机制实现了高精度事件采样。PEBS通过硬件在计数器溢出时将处理器现场直接保存到内存(而不是在响应中断时才保存寄存器现场),从而使得 perf能够采到真正触发性能事件的那条指令的地址,提高了采样精度。在默认条件下,perf不使用PEBS机制。
用户如果想要使用高精度采样,需要在指定性能事件时,在事件名后添加后缀”:p”或”:pp”。Perf在采样精度上定义了4个级别,如下表所示。
- 0: 无精度保证
- 1: 采样指令与触发性能事件的指令之间的偏差为常数(:p)
- 2: 需要尽量保证采样指令与触发性能事件的指令之间的偏差为0(:pp)
- 3: 保证采样指令与触发性能事件的指令之间的偏差必须为0(:ppp)
性能事件的精度级别目前的X86处理器,包括Intel处理器与AMD处理器均仅能实现前 3 个精度级别。
除了精度级别以外,性能事件还具有其它几个属性,均可以通过”event:X”的方式予以指定。
- u: 仅统计用户空间程序触发的性能事件
- k: 仅统计内核触发的性能事件
- h: 仅统计Hypervisor触发的性能事件
- G: 在KVM虚拟机中,仅统计Guest系统触发的性能事件
- H: 仅统计 Host 系统触发的性能事件
- p: 精度级别
2. Perf实际命令
- Tutorial - Perf Wiki (kernel.org)
2.1 perf命令
- perf(1) - Linux manual page (man7.org)
该命令支持的参数如下:
# perf命令的一般形式
perf [--version] [--help] [OPTIONS] COMMAND [ARGS]
# 目前支持的选项参数:
--help, Run perf help command. 运行perf help命令.
--version, 显示perf的版本信息
-vv, 打印库的编译状态。
--exec-path, Display or set exec path. 显示或者设置执行路径
--html-path, Display html documentation path. 显示html文档的路径
--paginate, Set up pager.
--no-pager, Do not set pager.
--debugfs-dir, Set debugfs directory or set environment variable PERF_DEBUGFS_DIR.
--buildid-dir, Setup buildid cache directory. It has higher priority than buildid.dir config file option.
--list-cmds, List the most commonly used perf commands.
--list-opts, List available perf options.
--debug, Setup debug variable (see list below) in value range (0, 10).
对于debug模式可以按照以下的方式进行设定:
--debug verbose # 表示设置verbose = 1
--debug verbose=2 # 表示设置verbose = 2
# 如verbose这样被允许设置的变量如下:
verbose - general debug messages
ordered-events - ordered events object debug messages
data-convert - data convert command debug messages
stderr - write debug output (option -v) to stderr in browser mode
perf-event-open - Print perf_event_open() arguments and return value
Perf Tool 是一个用户态工具集,包含了多种子工具集,下表具体介绍每种工具的基本功能:
名称 | 功能描述 |
---|---|
annotate | 读取perf.data, 对特定函数进行详细的分析,显示源代码或汇编级别的信息。 |
archive | 创建一个包含性能数据分析所需的二进制文件、调试信息和构建 ID 的归档文件。这个归档文件可以在其他系统上使用 perf report 命令进行分析,尤其是在那些没有原始二进制文件和调试信息的系统上。 |
bench | 用于运行内置的微基准测试(micro-benchmark),以评估和比较不同系统和内核配置下的性能。它提供了一组预定义的基准测试,包括调度器(scheduler)/内存子系统/锁操作/NUMA访问性能等. |
buildid-cache | 用于管理 perf 工具中的构建 ID 缓存。构建 ID 是一种唯一标识符,用于关联可执行文件、共享库或内核模块及其对应的调试信息。perf buildid-cache 可以添加、删除或列出构建 ID 缓存中的项。 |
buildid-list | 用于列出与 perf.data 文件相关的构建 ID。构建 ID 是一种唯一标识符,用于关联可执行文件、共享库或内核模块及其对应的调试信息。当你使用 perf record 收集性能数据时,这些构建 ID 会被存储在 perf.data 文件中。 |
c2c | (cache-to-cache)命令是一个用于分析内存访问和缓存行命中/未命中性能的工具。它专注于分析多核系统中的缓存行竞争和伪共享问题。伪共享是指多个核心访问同一个缓存行上的不同数据,导致缓存行频繁在核心之间迁移,从而降低整体性能。 |
config | 用于查询和修改 perf 工具的配置选项。这些配置选项控制 perf 工具的各种行为,例如默认的事件类型、显示样式、颜色方案等。perf 的配置信息存储在一个名为 perfconfig 的文件中,通常位于用户的主目录下(~/.perfconfig )或系统范围的配置文件中(/etc/perfconfig )。 |
daemon | Run record sessions on background,在后台运行采样程序。 |
data | 用于处理和管理 perf 工具生成的性能数据文件(通常为 perf.data )。这些文件包含了通过 perf record 命令收集的性能事件样本,可以用于进一步的性能分析和报告 |
diff | 用于比较两个或多个 perf.data 文件,以找出性能变化。这可以帮助你在优化代码或调整系统配置时,快速识别导致性能变化的原因。perf diff 通过计算事件计数器的差异以及其他性能指标来实现这一目标 |
evlist | 用于显示已配置的性能事件列表。这些事件在使用 perf record 命令收集性能数据时被记录。事件可以是硬件计数器事件(如 CPU 周期、缓存命中/未命中等)或软件事件(如上下文切换、页面错误等) |
ftrace | simple wrapper for kernel’s ftrace functionality,对内核ftrace功能进行简单的包装。 |
inject | 用于在已有的 perf.data 文件中插入或修改性能事件记录。这允许你在不重新收集性能数据的情况下,修改现有的性能数据文件以用于进一步的分析。perf inject 可以用于添加新事件、修改现有事件或删除不需要的事件 |
iostat | 用于监控系统的 I/O(输入/输出)性能。它可以实时显示系统的磁盘I/O操作情况,帮助你识别可能的I/O瓶颈。perf iostat 是由 perf 工具提供的一个额外命令,它基于 perf 收集的数据来生成类似于传统 iostat 命令的报告。 |
kallsyms | 用于显示内核符号表信息。内核符号表包含了内核函数、变量和其他内核对象的名称以及它们在内存中的地址。通过查看内核符号表,你可以更好地了解内核的结构和运行时行为。 |
kmem | 用于分析内核内存分配器的行为。内核内存分配器负责管理内核空间的内存资源。perf kmem 可以帮助你识别内核内存分配器的性能瓶颈和内存泄漏等问题,从而提高系统的性能和稳定性。 |
kvm | 用于分析和报告 KVM(Kernel-based Virtual Machine)虚拟化环境的性能。KVM 是 Linux 上的一个开源虚拟化技术,允许运行多个虚拟机(也称为客户机)在同一台物理主机上。perf kvm 可以帮助你识别虚拟环境中的性能瓶颈,从而提高虚拟机的性能和资源利用率。 |
list | 用于列出可用的性能事件,这些事件可以用于 perf record 和其他 perf 子命令的性能分析。性能事件包括硬件事件(如 CPU 周期、缓存未命中等)、软件事件(如上下文切换、页面错误等)和跟踪点事件(如内核函数调用、用户空间应用程序的跟踪等) |
lock | 用于分析锁竞争和锁相关性能问题。在多线程编程中,锁是一种同步原语,用于确保多个线程在访问共享资源时能够保持一致性。然而,锁的使用可能导致竞争和性能瓶颈。 |
mem | 用于分析内存访问性能,包括内存访问的延迟、带宽和缓存行命中率等。内存访问性能对于应用程序和系统的整体性能至关重要。 |
record | 用于记录性能事件,它依据用户指定的事件类型、采样频率和目标应用程序/进程来收集性能数据。 |
report | 用于分析和显示由 perf record 命令收集的性能数据。perf report 从 perf.data 文件(默认)中读取数据,然后生成一个性能报告,报告中包含各种统计信息和指标。 |
sched | 用于分析和调试 Linux 调度器(scheduler)的性能。调度器负责管理进程和线程的执行,优化 CPU 使用率和系统响应时间。 |
script | 用于处理并显示由 perf record 命令收集的性能事件数据。与 perf report 不同,perf script 提供了一种以原始格式显示性能数据的方法,这对于自定义分析、生成时间线以及与其他工具集成尤为有用。 |
stat | 用于收集并显示指定程序或系统的性能统计信息。它可以监控各种硬件性能事件(如 CPU 周期、缓存命中/未命中等)以及软件性能事件(如上下文切换、进程迁移等)。 |
test | 用于检查perf 工具的功能和正确性。它运行一系列内置的自我测试,以确保perf 在当前系统上可以正常工作。 |
timechart | 用于可视化系统级性能数据。它从perf 记录的性能事件数据中生成一张交互式的时间图表,展示系统活动和资源利用率随时间的变化。 |
top | 用于实时显示系统中占用CPU时间最多的函数,监控程序运行时的CPU利用情况,了解系统中哪些函数或代码片段对性能影响最大。 |
version | 显示perf可执行文件的版本信息 |
probe | 用于动态添加探针(probe)点,以便在特定函数或代码位置收集性能数据。 |
trace | 用于跟踪和记录系统调用、信号以及其他内核事件。分析程序与操作系统之间的交互,了解内核事件对程序性能的影响,诊断系统调用的错误和异常,帮助定位问题。 |
2.2 perf list 查看支持的性能事件
- perf-list(1) - Linux manual page (man7.org)
perf工具支持一系列可测量的事件。该工具和底层内核接口可以测量来自不同来源的事件。例如,有些事件是纯内核计数器,在这种情况下称为软件事件。例如:上下文切换、小故障。
事件的另一个来源是处理器本身及其性能监控单元(PMU)。它提供了一个事件列表来测量微体系结构事件,如周期数、指令退役、L1缓存缺失等。这些事件被称为PMU硬件事件或简称硬件事件。它们因处理器类型和型号而异。
perf_events接口还提供了一组常用的硬件事件名称。在每个处理器上,如果这些事件存在,则将它们映射到CPU提供的实际事件上,否则无法使用事件。有些令人困惑的是,这些事件也称为硬件事件(hardware event)和硬件缓存事件(hardware cache event)。
最后,还有由内核ftrace基础设施实现的tracepoint事件。这些仅在2.6.3 3x和更新的内核中可用。
命令帮助信息如下:
onceday->~:# perf list -h
Usage: perf list [<options>] [hw|sw|cache|tracepoint|pmu|sdt|metric|metricgroup|event_glob]
-d, --desc Print extra event descriptions. --no-desc to not print.
-v, --long-desc Print longer event descriptions.
--debug Enable debugging output
--deprecated Print deprecated events.
--details Print information on the perf event names and expressions used internally by events.
下面是一个实际输出,该命令显示可在使用-e选项的各种perf命令中选择的符号事件类型:
onceday->~:# perf list
List of pre-defined events (to be used in -e):
branch-misses [Hardware event]
bus-cycles [Hardware event]
cache-misses [Hardware event]
cache-references [Hardware event]
cpu-cycles OR cycles [Hardware event]
instructions [Hardware event]
alignment-faults [Software event]
bpf-output [Software event]
context-switches OR cs [Software event]
cpu-clock [Software event]
cpu-migrations OR migrations [Software event]
dummy [Software event]
emulation-faults [Software event]
major-faults [Software event]
minor-faults [Software event]
page-faults OR faults [Software event]
task-clock [Software event]
L1-dcache-load-misses [Hardware cache event]
L1-dcache-loads [Hardware cache event]
L1-dcache-store-misses [Hardware cache event]
L1-dcache-stores [Hardware cache event]
L1-icache-load-misses [Hardware cache event]
L1-icache-loads [Hardware cache event]
branch-load-misses [Hardware cache event]
branch-loads [Hardware cache event]
dTLB-load-misses [Hardware cache event]
dTLB-store-misses [Hardware cache event]
iTLB-load-misses [Hardware cache event]
node-loads [Hardware cache event]
node-stores [Hardware cache event]
armv8_cortex_a72/br_mis_pred/ [Kernel PMU event]
armv8_cortex_a72/br_pred/ [Kernel PMU event]
...(省略大量其他输出内容)...
PMU硬件事件是特定于CPU的,并由CPU供应商记录。如果链接到libpfm4, perf工具库会提供一些事件的简短描述。有关Intel和AMD处理器的PMU硬件事件列表,请参见:
- Intel® 64 and IA-32 Architectures Developer’s Manual: Vol. 3B
- BIOS and Kernel Developer’s Guide (BKDG) For AMD Family 10h Processors
perf list列出来的这些事件就是本机设备上受支持性能事件,后面中括号里面就是具体的事件类型,这些事件可能会非常多,不同的账户权限执行的结果也会有些不同。
对于非root用户,通常只有上下文切换的PMU事件可用。这通常只是cpu PMU中的事件、预定义的事件(如周期和指令)以及一些软件事件。其他pmu和全局测量通常仅为root
可用。一些事件限定符,如“any”,也是root
限定符。这可以通过设置kernel.perf_event_paranoid
为-1
来修改(使用sysctl),允许非root用户使用这些事件。为了访问跟踪点事件,perf
需要对/sys/kernel/debug/tracing具有读访问权限,即使perf_event_paranoid
处于宽松设置中也是如此。
2.3 perf 性能事件修饰符
- Tutorial - Perf Wiki (kernel.org)
对于任何受支持的事件,perf可以在流程执行期间保持运行计数。在计数模式中,事件的发生只是聚合在一起,并在应用程序运行结束时显示在标准输出上。要生成这些统计信息,可以使用perf的stat命令。例如:
onceday->~:# perf stat -B dd if=/dev/zero of=/dev/null count=1000000
1000000+0 records in
1000000+0 records out
512000000 bytes (512 MB, 488 MiB) copied, 4.01987 s, 127 MB/s
Performance counter stats for 'dd if=/dev/zero of=/dev/null count=1000000':
2239.106840 task-clock (msec) # 0.556 CPUs utilized
10041 context-switches # 0.004 M/sec
0 cpu-migrations # 0.000 K/sec
145 page-faults # 0.065 K/sec
2665504250 cycles # 1.190 GHz
2338072047 instructions # 0.88 insn per cycle
<not supported> branches
6692430 branch-misses
4.027916520 seconds time elapsed
在没有指定事件的情况下,perf stat收集上面列出的常见事件。有些是软件事件,如上下文切换,有些是一般的硬件事件,如循环。
可以在每次运行perftool时测量一个或多个事件。事件是用它们的符号名和可选的单位掩码和修饰符来指定的。事件名称(Event names)、单元掩码(unit masks)和修饰符(modifiers)不区分大小写。
默认情况下,事件是在用户和内核级别度量的:
perf stat -e cycles dd if=/dev/zero of=/dev/null count=100000
若要仅在用户级别进行度量,则需要传递一个修饰符(u):
perf stat -e cycles:u dd if=/dev/zero of=/dev/null count=100000
要测量用户和内核(显式地):
perf stat -e cycles:uk dd if=/dev/zero of=/dev/null count=100000
事件可以通过附加冒号和一个或多个修饰符来选择具有修饰符。修饰符允许用户限制何时对事件进行计数。修饰符如下:
名称标识 | 描述 |
---|---|
u | user-space counting,用户空间 |
k | kernel counting,内核空间 |
h | hypervisor counting,虚拟机 |
I | non idle counting,非空闲时 |
G | guest counting (in KVM guests),KVM虚拟机 |
H | host counting (not in KVM guests),KVM主机 |
p | precise level,硬件事件精度级别 |
P | use maximum detected precise level,使用最大检测精度水平 |
S | read sample value (PERF_SAMPLE_READ)读取样本值 |
D | pin the event to the PMU,将事件绑定到PMU上 |
W | 组是弱的,如果不可调度,将退回到非组 |
e | 群组或事件是排他性的,不共享PMU |
p修饰符可用于指定指令地址的精确程度。p修饰符可以被指定多次:
- 0 - SAMPLE_IP可以任意滑动
- 1 - SAMPLE_IP必须有恒定的滑动
- 2 - SAMPLE_IP要求有O滑块
- 3 - SAMPLE_IP必须有0滑块,或者使用随机化来避免样本副作用效果。
对于英特尔系统,精确事件采样是用PEBS实现的,它支持精确级别2,在某些特殊情况下支持精确级别3。
在AMD系统上,它是使用IBS实现的(最高精确级别到2)。精确修饰符与事件类型0x76 (cpu-cycles,CPU时钟未停止)和0xC1(micro-ops retired)一起工作。
2.4 测量特定硬件上的PMU事件
即使现在在perf中没有符号形式的事件,也可以用特定于每个处理器的方式对其进行编码。
比如对于X86CPUs,要测量CPU硬件供应商文档中提供的实际PMU,可以传递十六进制参数代码:
perf stat -e r1a8 -a sleep 1
perf record -e r1a8 ...
有些处理器,比如AMD的处理器,支持大于一个字节的事件代码和单元掩码。在这种情况下,与事件配置参数对应的位可以参考下面命令的结果:
cat /sys/bus/event_source/devices/cpu/format/event
比如可能的命令如下:
perf record -e r20000038f -a sleep 1
perf record -e cpu/r20000038f/ ...
perf record -e cpu/r0x20000038f/ ...
有关于特定硬件上的PMU事件,需要参考处理器的说明文档来确定使用方法。
在下面的路径可以查看可用的PMUs和它们的原始参数:
ls /sys/devices/*/format
一些pmu不与核心相关联,而是与整个CPU socket
相关联。这些pmu上的事件通常不能采样,只能使用perf stat -a
进行全局计数。它们可以绑定到一个逻辑CPU,但是会测量同一个插槽中的所有CPU。
本例在Intel Xeon系统的socket 0
上的第一个内存控制器上每秒测量内存带宽:
perf stat -C 0 -a uncore_imc_0/cas_count_read/,uncore_imc_0/cas_count_write/ -I 1000 ...
每个内存控制器都有自己的PMU。测量整个系统带宽需要指定所有imc pmu(请参阅perf list output),并将这些值相加。为了简化多个事件的创建,在PMU名称中支持前缀和全局匹配,并且在执行匹配时也忽略前缀uncore_。因此,上面的命令可以通过使用以下语法扩展到所有内存控制器:
perf stat -C 0 -a imc/cas_count_read/,imc/cas_count_write/ -I 1000 ...
perf stat -C 0 -a *imc*/cas_count_read/,*imc*/cas_count_write/ -I 1000 ...
2.5 参数化的性能事件
有一些pmu事件列出来的时候,其显示字符中带有?
号。如下:
hv_gpci/dtbp_ptitc,phys_processor_idx=?/
这意味着当作为事件提供时,?
所指示的内容必须也可提供。
perf stat -C 0 -e 'hv_gpci/dtbp_ptitc,phys_processor_idx=0x2/' ...
此外还有可能指定额外的事件修饰符(percore):
perf stat -e cpu/event=0,umask=0x3,percore=1/
上面命令即汇总一个核心中所有硬件线程的事件计数。
2.6 事件组测量
当活动事件的数量超过硬件性能计数器的数量时,Perf支持基于时间的事件复用。当工作负载更改其执行配置文件时,多路复用可能导致测量错误。
当使用来自事件计数的公式计算度量时,确保始终将一些事件作为一个组一起测量以最小化多路错误是很有用的。事件组可以使用{}
指定。
perf stat -e '{instructions,cycles}' ...
可用性能计数器的数量取决于CPU。一个组不能包含比可用计数器更多的事件。例如,Intel Core cpu通常有四个通用的核心性能计数器,加上三个固定的instructions
、cycles
和ref-cycles
计数器。一些特殊事件对它们可以调度的计数器有限制,并且可能不支持单个组中的多个实例。当组中指定的事件太多时,其中一些事件将无法测量。
全局固定事件可以限制其他组可用的计数器数量。在x86系统上,NMI看门狗默认固定一个计数器。NMI看门狗可以在root用户下禁用:
echo 0 > /proc/sys/kernel/nmi_watchdog
来自多个不同pmu的事件不能混合在一个组中,软件事件除外。
perf还支持使用:S
说明符进行组领导抽样(group leader sampling
)。
perf record -e '{cycles,instructions}:S' ...
perf report --group
通常情况下,所有事件都在一个事件组样本中,但是使用:S
时,只有第一个事件(leader)进行采样,它只读取组中其他事件的值。然而,在AUX区域事件(例如Intel PT或CoreSight)的情况下,AUX区域事件必须是先导事件,因此第二个事件采样,而不是第一个事件。
2.7 perf list性能事件分类
默认情况下,perf list列出所有的已知事件。也可以通过下面的类别来列出其中某一类事件:
事件类名称 | 描述 |
---|---|
hw or hardware | 列出硬件事件,如cache-misses |
sw or software | 列出软件事件,例如上下文切换(context switches) |
cache or hwcache | 列出硬件缓存事件,如L1-dcache-loads |
tracepoint | 列出所有的tracepoint事件,也可使用subsys_glob:event_glob去过滤子系统追踪点事件,如sched、block等。 |
pmu | 打印内核提供的PMU事件 |
sdt | 列出所有静态定义的跟踪点事件(Statically Defined Tracepoint) |
metric | 指标列表(度量事件) |
metricgroup | 列出带有指标的指标组 |
–raw-dump | 显示所有事件的原始格式信息,该选项后面可以接[hw|sw|cache|tracepoint|pmu|event_glob]、 |
(本文章为系列文章,未完待续)