Linux之perf(5)record统计
Author:Onceday Date:2023年9月23日
漫漫长路,才刚刚开始...
注:该文档内容采用了GPT4.0生成的回答,部分文本准确率可能存在问题。
参考文档:
文章目录
-
-
- Linux之perf(5)record统计
-
- [1. 概述](#1. 概述)
- [1.1 参数概览](#1.1 参数概览)
- [2. 功能描述](#2. 功能描述)
-
- [2.1 指定性能事件](#2.1 指定性能事件)
- [2.2 事件过滤器](#2.2 事件过滤器)
- [2.3 排除perf自身事件影响](#2.3 排除perf自身事件影响)
- [2.4 记录子线程的性能事件](#2.4 记录子线程的性能事件)
- [2.5 收集数据的优先级](#2.5 收集数据的优先级)
- [2.6 不带缓冲收集数据](#2.6 不带缓冲收集数据)
- [2.7 设置事件采样周期](#2.7 设置事件采样周期)
- [2.8 设置性能分析的频率](#2.8 设置性能分析的频率)
- [2.9 指定内存映射规格](#2.9 指定内存映射规格)
- [2.10 设置调用图记录](#2.10 设置调用图记录)
- [2.11 记录采样时间戳](#2.11 记录采样时间戳)
- [2.12 记录采样的标识符](#2.12 记录采样的标识符)
- [2.13 指定CPU](#2.13 指定CPU)
- [2.14 构建ID](#2.14 构建ID)
- [2.15 监视指定cgroup中程序的性能](#2.15 监视指定cgroup中程序的性能)
- [2.16 分支采样和过滤](#2.16 分支采样和过滤)
- [2.17 加权采样](#2.17 加权采样)
- [2.18 每线程采样](#2.18 每线程采样)
- [2.19 延迟测量](#2.19 延迟测量)
- [2.20 中断时捕获机器状态](#2.20 中断时捕获机器状态)
- [2.21 记录启动和运行时间](#2.21 记录启动和运行时间)
- [2.22 记录时钟字段的时钟ID](#2.22 记录时钟字段的时钟ID)
- [2.23 选择 AUX 区域跟踪的快照模式](#2.23 选择 AUX 区域跟踪的快照模式)
- [2.24 异步模式配置](#2.24 异步模式配置)
- [2.25 设置追踪线程的掩码](#2.25 设置追踪线程的掩码)
- [2.26 指定从 mmap 数据页提取并进行输出处理的最小字节数](#2.26 指定从 mmap 数据页提取并进行输出处理的最小字节数)
- [2.27 使用指定的级别 `n` 生成压缩的跟踪](#2.27 使用指定的级别
n
生成压缩的跟踪) - [2.28 perf.data文件配置](#2.28 perf.data文件配置)
- [2.29 只运行命令,不产生实际效果](#2.29 只运行命令,不产生实际效果)
- [2.30 收集和合成指定类型的事件](#2.30 收集和合成指定类型的事件)
- [2.31 覆写旧数据](#2.31 覆写旧数据)
- [2.32 动态控制性能测量开关](#2.32 动态控制性能测量开关)
- [2.33 使用并行线程进行数据处理](#2.33 使用并行线程进行数据处理)
- [2.34 使用 BPF 启用 off-cpu 分析](#2.34 使用 BPF 启用 off-cpu 分析)
- 3.Inter混合平台支持
-
- [2.34 使用 BPF 启用 off-cpu 分析](#2.34 使用 BPF 启用 off-cpu 分析)
- 3.Inter混合平台支持
-
1. 概述
这个命令会运行一个命令,并从中收集性能计数器的信息,将其存储到 perf.data
文件中,过程中并不显示任何内容。
然后,你可以使用 perf report
命令在后续进行审查这个文件。
这里有一个简单的例子:
首先,我们运行 perf record
来收集性能数据:
bash
$ perf record -F 99 -p 12345 # 99 是采样率,12345 是进程ID
上述命令会将性能数据存储到 perf.data
文件中。
然后,我们可以使用 perf report
来检查这个文件:
bash
$ perf report # 这会显示 perf.data 文件中的信息
perf report
默认会读取 perf.data
文件,你也可以指定一个不同的文件进行读取。
1.1 参数概览
参数 | 描述 |
---|---|
[command] | Any command you can specify in a shell. 具体执行的命令 |
-e,--event | 选择性能监控单元事件 |
--filter=[filter] | 事件过滤器 |
--exclude-perf | 不记录由 perf 本身发出的事件。 |
-a, --all-cpus | 在整个系统的范围记录事件(所有CPU),默认开启。 |
-p, --pid= | 在特定的进程上记录事件,多个进程ID用逗号分割。 |
-t, --tid= | 在指定的线程上记录事件,默认关闭继承(inheritance)。 |
-u, --uid= | 记录指定用户所属线程的事件,名字或者ID。 |
-r, --realtime= | 以此 RT SCHED_FIFO 优先级收集数据。 |
--no-buffering | 收集数据时不进行缓冲。 |
-c, --count= | 设置事件采样周期,即事件发生多少次后采样一次。 |
-o, --output= | 指定输出文件的名字 |
-i, --no-inherit | 子线程或者进程不继承性能计数任务, |
-F, --freq= | 设置性能分析的频率 |
--strict-freq | 如果指定的分析频率无法实现,那么直接失败退出 |
-m, --mmap-pages= | 指定内存映射页数或者大小 |
-g | 使能调用栈/链追踪,内核和用户空间都生效 |
--call-graph | 设置并启用调用图记录,包含-g 的功能,可以指定调用链追踪的方法。 |
-q, --quiet | Don't print any warnings or messages, useful for scripting. |
-v, --verbose | Be more verbose (show counter open errors, etc). |
-s, --stat | 记录每个线程的事件计数。与 perf report -T 一起使用,可以查看这些值。 |
-d, --data | 记录采样的虚拟地址 |
--phys-data | 记录采样的物理地址 |
--data-page-size | Record the sampled data address data page size.。 |
--code-page-size | Record the sampled code address (ip) page size。 |
-T, --timestamp | 记录采样时间戳 |
-P, --period | 记录采样周期 |
--sample-cpu | Record the sample cpu. |
--sample-identifier | 记录采样的标识符 |
-n, --no-samples | Don't sample. |
-R, --raw-samples | Collect raw sample records from all opened counters (default for tracepoint counters). |
-C, --cpu | 指定采样的CPU列表,逗号分割,或者破折号。 |
-B, --no-buildid | 不保存二进制文件构建ID |
-N, --no-buildid-cache | 不更新构建 ID 缓存 |
-G name,..., --cgroup name,... | 只在名为 "name" 的容器(cgroup)中监视 |
-b, --branch-any | 启用已采样的分支堆栈取样 |
-j, --branch-filter | 启用过滤器来选择捕获的分支类型 |
-W, --weight | 加权采样 |
--namespaces | Record events of type PERF_RECORD_NAMESPACES. This enable cgroup_id sort key. |
--all-cgroups | Record events of type PERF_RECORD_CGROUP. This enables cgroup sort key. |
--transaction | Record transaction flags for transaction related events. |
--per-thread | 使用每线程的内存映射(mmaps) |
-D, --delay= | 启动程序后,等待 msecs(毫秒)再开始测量 |
-I, --intr-regs | 在中断时捕获机器状态(寄存器) |
--user-regs | 类似于 -I ,但在采样时捕获用户空间寄存器 |
--running-time | 记录读取事件(:S)的运行时间和启用时间 |
-k, --clockid | 记录中各种时间字段的时钟 ID |
-S, --snapshot | 选择 AUX 区域跟踪的快照模式 |
--aux-sample[=OPTIONS] | 选择 AUX 区域采样 |
--proc-map-timeout | 内存映射(/proc/xx/mmap)超时时间,默认500ms |
--switch-events | 记录上下文切换事件,(Intel PT, CoreSight or Arm SPE)等自动激活 |
--clang-path=PATH | clang程序路径,用于编译BPF |
--clang-opt=OPTIONS | 编译BPF时传递给clang的参数 |
--vmlinux=PATH | Specify vmlinux path which has debuginfo. (enabled when BPF prologue is on) |
--buildid-all | Record build-id of all DSOs regardless whether it's actually hit or not. |
--buildid-mmap | Record build ids in mmap2 events, disables build id cache (implies --no-buildid). |
--aio[=n] | 在异步(Posix AIO)跟踪写入模式中使用 <n> 个控制块 |
--affinity=mode | 设置跟踪读取线程的亲和性掩码 |
--mmap-flush=number | 指定从 mmap 数据页提取并进行输出处理的最小字节数 |
-z, --compression-level[=n] | 使用指定的级别 n 生成压缩的跟踪 |
--all-kernel | 配置所有使用的事件在内核空间运行。 |
--all-user | 配置所有使用的事件在用户空间运行。 |
--kernel-callchains | 仅从内核空间收集调用链,perf_event_attr.exclude_callchain_user 设置为1。不能同时使用这两个选项,否则将不会收集到任何调用链。 |
--user-callchains | 仅从用户空间收集调用链,perf_event_attr.exclude_callchain_kernel 设置为1。不能同时使用这两个选项,否则将不会收集到任何调用链。 |
--timestamp-filename | 在输出文件名后追加时间戳。 |
--timestamp-boundary | 记录时间戳边界(第一个/最后一个样本的时间) |
--switch-output[=mode] | 生成多个时间戳前缀的 perf.data 文件 |
--switch-output-event | 将导致切换 perf.data 文件的事件,自动选择 --switch-output=signal |
--switch-max-files=N | 在使用 --switch-output 旋转 perf.data 时,只保留 N 个文件 |
--dry-run | 检测命令行选项中的错误 |
--synth=TYPE | 收集和合成指定类型的事件(用逗号分隔) |
--tail-synthesize | 在记录结束时,收集非样本事件(例如,fork,comm,mmap)。 |
--overwrite | 使所有事件使用可覆写的环形缓冲区 |
-kcore | 复制 /proc/kcore 的内容,并将其放入包含 perf 数据文件的目录中。 |
--max-size=[size] | 限制样本数据的最大大小,<size> 预期是一个带有附加单位字符的数字 - B(字节)/K(千字节)/M(兆字节)/G(吉字节)。 |
--num-thread-synthesize | 指定在为现有进程合成事件时运行的线程数。默认情况下,线程数等于1。 |
--control | --control=fifo:ctl-fifo[,ack-fifo], --control=fd:ctl-fd[,ack-fd],动态控制性能测量开关 |
--threads=[spec] | 使用并行线程进行数据处理 |
--debuginfod[=URLs] | 指定在缓存 perf.data 二进制文件时要使用的 debuginfod URL |
--off-cpu | 使用 BPF 启用 off-cpu 分析 |
2. 功能描述
2.1 指定性能事件
-e, --event=
参数用于选择 PMU(Performance Monitoring Unit,性能监控单元)事件。选择可以是:
-
一个符号化的事件名称(使用
perf list
来列出所有事件) -
一个原始的 PMU 事件,形式为 rN,其中 N 是代表事件控制寄存器布局的原始寄存器编码的十六进制值,这些布局描述在
/sys/bus/event_source/devices/cpu/format/*
中。 -
一个符号化或原始的 PMU 事件,后面可以跟一个可选的冒号和事件修饰符列表,例如,
cpu-cycles:p
。关于事件修饰符的详细信息,可参见perf-list(1)
手册页面。 -
一个符号形式的 PMU 事件,如
pmu/param1=0x3,param2/
,其中 param1、param2 等是在/sys/bus/event_source/devices/<pmu>/format/*
中定义的 PMU 的格式。 -
一个符号形式的事件,如
pmu/config=M,config1=N,config3=K/
,其中 M、N、K 是数字(十进制、十六进制、八进制格式)。'config'、'config1' 和 'config2' 的可接受值由/sys/bus/event_source/devices/<pmu>/format/*
中的对应条目定义。param1 和 param2 是在/sys/bus/event_source/devices/<pmu>/format/*
中定义为 PMU 的格式。
还有一些参数并未在 .../<pmu>/format/*
中定义。这些参数可以用来覆盖每个事件的默认配置值。以下是一些常见参数:
- 'period': 设置事件采样周期
- 'freq': 设置事件采样频率
- 'time': 禁用/启用时间戳。可接受的值为 1(启用时间戳)和 0(禁用时间戳)。默认值为 1。
- 'call-graph': 禁用/启用调用图。可接受的字符串有 "fp"(FP模式),"dwarf"(DWARF模式),"lbr"(LBR模式)和 "no"(禁用调用图)。
- 'stack-size': dwarf 模式下的用户堆栈大小
- 'name': 用户定义的事件名称。可以使用单引号 (') 来避免 shell 和工具解析名称中的符号,例如:name='CPU_CLK_UNHALTED.THREAD:cmask=0x1'。
- 'aux-output': 生成 AUX 记录而不是事件。这需要提供一个 AUX 区域事件。
- 'aux-sample-size': 设置 AUX 区域采样的样本大小。如果已经使用了 '--aux-sample' 选项,设置 aux-sample-size=0 可以禁用该事件的 AUX 区域采样。
更多参数,请参见 perf-list[1]
手册页面。
注意:如果用户明确设置了与参数冲突的选项,那么由参数设置的值将被覆盖。
PMU 驱动特定的配置参数也没有在 .../<pmu>/format/*
中定义。任何由 '@' 符号前缀的配置参数都不会在用户空间解析,并直接发送到 PMU 驱动。例如:
bash
perf record -e some_event/@cfg1,@cfg2=config/ ...
将会看到 'cfg1' 和 'cfg2=config' 被推送到与事件相关的 PMU 驱动进行进一步处理。只要这些配置参数的语义被 PMU 驱动理解和支持,就没有限制这些配置参数是什么。
-
一个硬件断点事件,形式为
\mem:addr[/len][:access]
,其中 addr 是你想要在内存中打断点的地址。access 是内存访问类型(读取,写入,执行),可以按照以下方式传递:\mem:addr[:[r][w][x]]
。len 是范围,从指定的 addr 开始的字节数,断点将覆盖这个范围。如果你想分析在 0x1000 的读写访问,只需设置mem:0x1000:rw
。如果你想分析在 [0x1000~1008) 的写入访问,只需设置mem:0x1000/8:w
。 -
一个 BPF 源文件(以 .c 结尾)或预编译的对象文件(以 .o 结尾)选择一个或多个 BPF 事件。BPF 程序可以基于 ELF section 名称附加到各种 perf 事件。
当处理 '.c' 文件时,perf 会搜索已安装的 LLVM 将其编译成对象文件。可选的 clang 选项可以通过 '--clang-opt' 命令行选项传递,例如:
bashperf record --clang-opt "-DLINUX_VERSION_CODE=0x50000" \ -e tests/bpf-script-example.c
注意:'--clang-opt' 必须放在 '--event/-e' 之前。
-
一个由一对大括号 ("{event1,event2,...}") 包围的事件组。每个事件由逗号分隔,组应被引用以防止 shell 解释。在 "perf report" 中查看组事件时,你还需要使用 --group 选项。
2.2 事件过滤器
事件过滤器。此选项应该跟随事件选择器(-e)。如果事件是跟踪点,过滤字符串将由内核解析。如果事件是硬件跟踪 PMU(例如 Intel PT 或 CoreSight),它将被处理为地址过滤器。否则,它表示可以应用于任何类型事件的通用 BPF 过滤器。
-
跟踪点过滤器,对于跟踪点,多个 '--filter' 选项将使用 '&&' 组合。
-
地址过滤器,硬件跟踪 PMU 通过在
/sys/bus/event_source/devices/<pmu>/nr_addr_filters
中指定非零值来宣告其接受多个地址过滤器的能力。地址过滤器的格式为:
filter|start|stop|tracestop start [<size>] [<file name>]
其中:
- 'filter': 定义将被跟踪的区域。
- 'start': 定义跟踪将开始的地址。
- 'stop': 定义跟踪将停止的地址。
- 'tracestop': 定义跟踪将停止的区域。
<file name>
是对象文件的名称,<start>
是该文件中要跟踪的代码的偏移,<size>
是要跟踪的区域的大小。'start' 和 'stop' 过滤器不需要指定<size>
。如果未指定对象文件,则假定为内核,在这种情况下,开始地址必须是当前的内核内存地址。
<start>
也可以通过提供符号名来指定。如果符号名不唯一,可以通过插入 #n 来消除歧义,其中 'n' 选择地址顺序中的第 n 个符号。或者,#0、#g 或 #G 仅选择全局符号。<size>
也可以通过提供符号名来指定,在这种情况下,大小计算到该符号的结束。对于 'filter' 和 'tracestop' 过滤器,如果省略了<size>
并且<start>
是一个符号,则大小计算到该符号的结束。如果省略了
<size>
并且<start>
是 '*',那么开始和大小将从第一个和最后一个符号计算,即跟踪整个文件。如果提供了符号名(或 '*'),它们必须被空白字符包围。传递给内核的过滤器不一定与输入的相同。要查看传递的过滤器,请使用 -v 选项。如果跟踪区域不在单个映射内,内核可能无法配置跟踪区域。可以检查 MMAP 事件(
/proc/<pid>/maps
)以确定是否可能。多个过滤器可以用空格或逗号分隔。 -
BPF 过滤器
BPF 过滤器可以访问样本数据并根据数据做出决定。用户需要设置一个合适的样本类型来使用 BPF 过滤器。BPF 过滤器需要 root 权限。
样本数据字段可以用小写字母指定。多个过滤器可以用逗号分隔。例如,
bash--filter 'period > 1000, cpu == 1'
或
bash--filter 'mem_op == load || mem_op == store, mem_lvl > l1'
前一个过滤器仅接受周期大于 1000 并且 CPU 编号为 1 的样本。后一个过滤器接受加载和存储内存操作,但它应该具有高于 L1 的内存级别。由于 mem_op 和 mem_lvl 字段来自 (memory) data_source,它只能与设置了 data_source 字段的一些事件一起工作。
此外,用户还应该请求收集该信息(如上例中的 -d 选项)。否则,将显示以下消息。
bash$ sudo perf record -e cycles --filter 'mem_op == load' Error: cycles event does not have PERF_SAMPLE_DATA_SRC Hint: please add -d option to perf record. failed to set filter "BPF" on event cycles with 22 (Invalid argument)
本质上,BPF 过滤表达式是:
yacas<term> <operator> <value> (("," | "||") <term> <operator> <value>)*
<term>
可以是以下之一:yacasip, id, tid, pid, cpu, time, addr, period, txn, weight, phys_addr, code_pgsz, data_pgsz, weight1, weight2, weight3, ins_lat, retire_lat, p_stage_cyc, mem_op, mem_lvl, mem_snoop, mem_remote, mem_lock, mem_dtlb, mem_blk, mem_hops
<operator>
可以是以下之一:yacas==, !=, >, >=, <, <=, &
<value>
可以是以下之一:yacas<number> (对于任何 term) na, load, store, pfetch, exec (对于 mem_op) l1, l2, l3, l4, cxl, io, any_cache, lfb, ram, pmem (对于 mem_lvl) na, none, hit, miss, hitm, fwd, peer (对于 mem_snoop) remote (对于 mem_remote) na, locked (对于 mem_locked) na, l1_hit, l1_miss, l2_hit, l2_miss, any_hit, any_miss, walk, fault (对于 mem_dtlb) na, by_data, by_addr (对于 mem_blk) hops0, hops1, hops2, hops3 (对于 mem_hops)
2.3 排除perf自身事件影响
不记录由 perf 本身发出的事件。此选项应跟随选择 tracepoint 事件的事件选择器(-e)。它将一个过滤表达式 common_pid != $PERFPID 添加到过滤器中。如果存在其他 --filter
,新的过滤表达式将通过 && 与它们结合。
这个选项的目的是防止 perf 从自身产生的事件中收集数据,这有助于防止在分析数据时产生噪声,并提高数据的准确性。它通过添加一个过滤器实现,这个过滤器会忽略所有来自 perf 进程 PID 的事件。
例如,如果你正在使用 perf 追踪一些特定的 tracepoint 事件,但不希望包含由 perf 本身产生的事件,你可以像下面这样使用 --exclude-perf
选项:
bash
perf record -e tp:event --exclude-perf
在这个例子中,perf 将记录所有 tp:event 事件,但会排除那些由 perf 进程产生的事件。如果存在其他过滤器,例如 --filter 'pid == 1234'
,那么 --exclude-perf
生成的过滤器将与现有的过滤器结合,形成一个复合过滤器,效果如下:
bash
perf record -e tp:event --filter 'pid == 1234' --exclude-perf
在这个例子中,perf 会记录所有 tp:event 事件,但只包含那些由进程 1234 产生的事件,并且排除由 perf 进程产生的事件。
2.4 记录子线程的性能事件
记录现有线程 ID 上的事件(用逗号分隔的列表)。这个选项默认也会禁用继承。通过添加 --inherit
来启用它。
由于 Linux 是一个多任务操作系统,一个进程可以拥有多个线程,每个线程都有自己的线程 ID(TID)。在某些情况下,你可能会希望只针对特定线程进行事件记录,而不是整个进程。这可以通过 -t
或 --tid
选项来实现,你只需要提供一个或多个你想要监视的线程 ID。
例如,如果你想要记录 TID 为 1234 和 5678 的线程的事件,你可以这样操作:
bash
perf record -t 1234,5678
默认情况下,使用 -t
或 --tid
选项将禁用事件的继承。这意味着,如果线程创建了新的子线程,那么这些子线程的事件不会被记录。如果你希望包括这些子线程的事件,你可以通过添加 --inherit
选项来实现:
bash
perf record -t 1234,5678 --inherit
在这个例子中,perf 将记录 TID 为 1234 和 5678 的线程及其所有子线程的事件。
2.5 收集数据的优先级
在 Linux 中,SCHED_FIFO(First In, First Out)是一种实时调度策略,它被设计为满足实时任务的需求,这些任务需要在尽可能短的时间内完成。使用 SCHED_FIFO 策略,线程一旦开始运行就不会被其他线程抢占,直到它自愿放弃 CPU 或完成任务。
-r
或 --realtime
选项允许你为 perf 数据收集操作指定一个 SCHED_FIFO 优先级。这个优先级的取值范围是 1(最低优先级)到 99(最高优先级)。设置较高的优先级意味着 perf 的数据收集操作将优先于其他非实时任务执行,这可以帮助减少数据收集过程中的延迟,提高数据的准确性。
例如,如果你想以优先级 99(最高优先级)收集数据,你可以使用如下命令:
bash
perf record -r 99
请注意,使用此选项可能需要特殊的系统权限,因为改变进程的调度策略和优先级可能会影响系统的稳定性和性能。在多任务系统中,过度优先考虑一个任务可能导致其他任务得不到足够的 CPU 时间。
2.6 不带缓冲收集数据
-no-buffering
无缓冲地收集数据。
在进行性能分析时,数据通常是首先被收集到一个缓冲区中,然后再进行进一步的处理和分析。这样的设计可以提高性能,因为缓冲区允许数据在被处理之前先进行集中存储,减少了频繁的磁盘 I/O 操作。
然而,缓冲区引入的延迟可能会影响到你对系统实时性能的理解。例如,在极端情况下,如果缓冲区的大小设置得过大,那么数据可能需要在缓冲区中停留很长时间才能被处理,这将导致你看到的性能数据与实际情况有所偏差。
-no-buffering
选项允许你关闭 perf 的数据收集缓冲区。在该模式下,perf 将立即处理所有收集到的数据,而不将其存储在缓冲区中。这可以提供更实时的性能数据,但可能会以牺牲总体性能为代价,因为频繁的磁盘 I/O 操作可能会对系统性能产生影响。
例如,如果你想无缓冲地收集数据,你可以使用如下命令:
bash
perf record -no-buffering
请注意,-no-buffering
选项可能会对 perf 的数据收集速度产生影响,特别是在高负载或高事件频率的环境中。因此,你应该根据你的具体需求和系统环境来权衡是否使用这个选项。
2.7 设置事件采样周期
在性能分析中,采样是最常用的数据收集方法之一。通过定期(或者说,每隔一定数量的事件)收集数据,你可以得到系统状态的快照,而无需记录每一个单独的事件。这种方法可以大大减少需要处理的数据量,从而提高性能分析的效率。
-c
或 --count
选项允许你设置 perf 的采样周期。这个周期是以事件数量为单位的。例如,如果你设置采样周期为 1000,那么 perf 就会在每 1000 个事件发生后进行一次采样。
例如,如果你想每 1000 个 CPU 周期进行一次采样,你可以使用如下命令:
bash
perf record -c 1000 -e cycles
在这个例子中,-e cycles
选择了 CPU 周期事件作为采样的对象。每当 CPU 执行 1000 个周期,perf 就会收集一次数据。
请注意,设置过小的采样周期可能会导致数据量过大,而设置过大的采样周期则可能会错过一些重要的信息。因此,你应该根据你的具体需求和系统环境来选择合适的采样周期。
2.8 设置性能分析的频率
以此频率进行性能分析。使用 max 来使用当前允许的最大频率,即 kernel.perf_event_max_sample_rate sysctl 中的值。将降低到当前允许的最大频率。参见 --strict-freq
。
-F
或 --freq
选项允许你设置 perf 进行性能分析的频率。频率是指每秒钟进行采样的次数。例如,如果你设置采样频率为 1000,那么 perf 就会每秒钟收集 1000 次数据。
如果你设置频率为 max
,那么 perf 将使用当前系统允许的最大采样频率。这个值可以在 kernel.perf_event_max_sample_rate
这个系统控制变量中找到。如果实际的采样频率超过了这个值,perf 将自动降低采样频率,以确保不会超过最大允许频率。
例如,如果你想以最大可能的频率进行采样,你可以使用如下命令:
bash
perf record -F max
--strict-freq
是一个相关的选项,它要求 perf 严格按照你指定的频率进行采样。如果因为某些原因(例如,系统负载过高)无法达到这个频率,perf 将停止数据收集。使用 --strict-freq
选项可以确保你得到的数据精度,但可能会以丢失一些数据为代价。
2.9 指定内存映射规格
该选项允许您指定用于数据映射的内存页数或带有单位字符(B/K/M/G)的大小规格。大小将四舍五入到最接近的2的幂值。此外,通过添加逗号,可以指定用于 AUX 区域跟踪的内存映射页数。
在 Linux 中,mmap 是一种将文件或其他对象映射到进程的地址空间的方法,这样进程就可以像访问普通内存一样访问这些对象。在 perf 中,mmap 用于存储采集的性能数据。
你可以指定 mmap 数据页的数量或大小。如果你指定的是数量,那么这个数量必须是 2 的幂;如果你指定的是大小,那么 perf 将四舍五入到最接近的 2 的幂值。这是因为,内存页的数量和大小通常最好是 2 的幂,这样可以提高内存管理的效率。
此外,你还可以指定用于 AUX 区域跟踪的 mmap 页数。AUX 区域是一种特殊的内存区域,用于存储一些特定类型的性能数据,比如硬件事件的记录。
例如,如果你想为数据映射设置 256 页,而为 AUX 区域设置 64 页,你可以使用如下命令:
bash
perf record -m 256,64
在这个例子中,-m 256,64
设置了数据映射的页数和 AUX 区域的页数。请注意,设置过小的页数或大小可能会导致数据丢失,而设置过大的页数或大小则可能会浪费内存。因此,你应该根据你的具体需求和系统环境来选择合适的值。
2.10 设置调用图记录
此选项用于设置并启用调用图(堆栈链/回溯)记录,暗含着 -g
的功能。默认为 "fp"(用户空间)。
用于内核空间的展开方法取决于活动内核配置使用的展开器,也就是:
yacas
CONFIG_UNWINDER_FRAME_POINTER(fp)或 CONFIG_UNWINDER_ORC(orc)
这里指定的任何选项都控制用户空间使用的方法。
有效的选项包括 "fp"(帧指针),"dwarf"(DWARF的CFI - Call Frame Information)或 "lbr"(硬件最后分支记录设施)。
在一些系统中,其中的二进制文件是用 gcc 的 --fomit-frame-pointer
选项构建的,使用 "fp" 方法将产生错误的调用图,如果可用(perf工具链接到libunwind或libdw库),应该使用 "dwarf" 来代替。使用 "lbr" 方法不需要任何编译器选项。它将从硬件的 LBR 寄存器产生调用图。主要的限制是它只在新的Intel平台上可用,比如 Haswell。它只能获取用户调用链,不能同时用于分支堆栈采样。
当使用 "dwarf" 记录时,perf也会在采样时记录(用户)堆栈dump。默认的堆栈dump大小为8192(字节)。用户可以通过在逗号后传递大小来更改大小,如 --call-graph dwarf,4096
。
当使用 "fp" 记录时,perf会尝试保存堆栈条目,数量默认为 sysctl.kernel.perf_event_max_stack 中指定的数量。用户可以通过在逗号后传递数量来更改,如 --call-graph fp,32
。
2.11 记录采样时间戳
-T, --timestamp
记录采样的时间戳。可以与perf report -D
一起使用,以查看时间戳。
这个选项可以帮助您理解程序的性能特性在时间上的变化。时间戳记录了每个样本被采集的具体时间,这可以帮助您发现程序在执行过程中的性能瓶颈。
例如,如果您想要记录某个进程的性能事件和对应的时间戳,可以使用以下命令:
bash
perf record -T -p [pid]
其中 [pid]
是您想要监控的进程的ID。然后,您可以使用以下命令查看采集数据的详细信息和对应的时间戳:
bash
perf report -D
2.12 记录采样的标识符
--sample-identifier
记录采样的标识符,即在调用perf_event_open
系统调用的struct perf_event_attr
参数中,sample_type
成员设置的PERF_SAMPLE_IDENTIFIER
位。
这个选项主要在处理复杂的性能事件采样场景中使用,它可以帮助您准确地识别每一个采样事件的来源。PERF_SAMPLE_IDENTIFIER
是一个唯一的标识符,用于关联一个特定的事件样本和它的来源事件。
例如,如果您有许多不同类型的事件正在同时被采样,您可能需要使用 --sample-identifier
选项来追踪每一个事件样本的来源。这可以帮助您更准确地理解各种事件如何影响程序的性能。
使用此选项的命令可能类似于以下形式:
bash
perf record --sample-identifier -e event1,event2,... -p [pid]
其中 event1,event2,...
是您想要监控的事件,[pid]
是您想要监控的进程的ID。然后,您可以使用 perf report
来查看和分析收集到的数据。
2.13 指定CPU
仅在提供的 CPU 列表上收集样本。可以提供多个 CPU,以无空格的逗号分隔列表形式提供:0,1。CPU 的范围可以用 -
指定:0-2。在线程继承模式开启(默认)的每线程模式下,只有当线程在指定的 CPU 上执行时才捕获样本。默认情况下是监视所有 CPU。
这个选项允许您在特定的 CPU 或 CPU 集合上收集性能数据。这可以帮助你更精确地理解程序在特定硬件环境下的性能。
例如,如果你想在 CPU 0 和 CPU 2 上记录某个进程的性能事件,你可以使用以下命令:
bash
perf record -C 0,2 -p [pid]
2.14 构建ID
不在 perf.data
文件中保存二进制文件的构建 ID。这会跳过记录后的后处理,有时这会使记录过程的最后一步耗时很长,因为它需要处理所有事件以寻找 mmap 记录。缺点是,如果在记录时使用的工作负载二进制文件被本地重建或升级,可能会错误解析符号,因为在这种情况下唯一可用的关键是路径名。您还可以设置 "record.build-id" 配置变量为 'skip',以永久地具有此行为。
这个选项的主要作用是加速 perf record
的执行,特别是在处理大量事件或大型二进制文件时。然而,这可能会导致在后续的符号解析阶段出现问题,特别是当你的程序或库在 perf record
执行后被修改或更新时。
例如,如果你想记录一个进程的性能事件,但不保存 buildid,你可以使用以下命令:
bash
perf record -B -p [pid]
其中 [pid]
是你想要监控的进程的 ID。然后,你可以使用 perf report
来查看和分析收集到的数据。
-N, --no-buildid-cache
,不更新构建 ID 缓存。在 perf.data 文件(其中包括构建 ID)的信息足够的情况下,这可以节省一些开销。您也可以将 "record.build-id" 配置变量设置为 no-cache,以产生相同的效果。
这个选项可以帮助你减少 perf record 的开销,特别是在处理大量事件或大型二进制文件时。然而,这可能会导致在后续的符号解析阶段出现问题,特别是当你需要使用构建 ID 缓存来解析符号时。
例如,如果你想记录一个进程的性能事件,但不更新构建 ID 缓存,你可以使用以下命令:
yacas
perf record -N -p [pid]
其中 [pid] 是你想要监控的进程的 ID。然后,你可以使用 perf report 来查看和分析收集到的数据。
2.15 监视指定cgroup中程序的性能
只在名为 "name" 的容器(cgroup)中监视。此选项仅在每 CPU 模式下可用。必须挂载 cgroup 文件系统。当它们在被监视的 CPU 上运行时,将监视属于 "name" 容器的所有线程。可以提供多个 cgroup。每个 cgroup 应用于相应的事件,即,第一个 cgroup 应用于第一个事件,第二个 cgroup 应用于第二个事件,依此类推。使用 -G foo,,bar
可以提供一个空的 cgroup(始终监视)。cgroup 必须有对应的事件,即,它们总是引用命令行上早期定义的事件。如果用户想要跟踪特定 cgroup 的多个事件,用户可以使用 -e e1 -e e2 -G foo,foo
或只使用 -e e1 -e e2 -G foo
。
如果想要监视,比如说,一个 cgroup 的周期,也要系统范围内的周期,可以使用这条命令行:perf stat -e cycles -G cgroup_name -a -e cycles
。
这个选项让你可以仅在特定的 cgroup 中收集性能数据。这对于理解在特定容器环境(例如 Docker 或 Kubernetes)中运行的程序的性能特性非常有用。
例如,如果你想在名为 "my_cgroup" 的 cgroup 中记录某个进程的性能事件,你可以使用以下命令:
bash
perf record -G my_cgroup -p [pid]
其中 [pid]
是你想要监控的进程的 ID。然后,你可以使用 perf report
来查看和分析收集到的数据。
2.16 分支采样和过滤
-
-b, --branch-any
,启用已采样的分支堆栈取样。可能采样任何类型的已采样分支。这是--branch-filter any
的快捷方式。有关更多信息,请参见--branch-filter
。 -
-j, --branch-filter
,启用已采样的分支堆栈取样。每个样本捕获一系列连续的已采样分支。每个样本捕获的分支数取决于底层硬件、感兴趣的分支类型和执行的代码。可以通过启用过滤器来选择捕获的分支类型。定义了以下过滤器:•
any
: 任何类型的分支•
any_call
: 任何函数调用或系统调用•
any_ret
: 任何函数返回或系统调用返回•
ind_call
: 任何间接分支•
ind_jmp
: 任何间接跳转•
call
: 直接调用,包括远程(到/从内核)调用•
u
: 只有当分支目标在用户级别时•
k
: 只有当分支目标在内核中时•
hv
: 只有当目标在虚拟机监视器级别时•
in_tx
: 只有当目标在硬件事务中时•
no_tx
: 只有当目标不在硬件事务中时•
abort_tx
: 只有当目标是硬件事务中止时•
cond
: 条件分支•
call_stack
: 保存调用栈•
no_flags
: 不保存分支标志,例如预测,错误预测等•
no_cycles
: 不保存分支周期•
hw_index
: 保存分支硬件索引•
save_type
: 在采样期间保存分支类型,以防后期无法获取二进制文件。对于具有 Intel Arch LBR 支持的平台(第 12 代+ 客户机或第 4 代 Xeon+ 服务器),在启用已采样的分支堆栈采样时,保存分支类型是无条件启用的。•
priv
: 在采样期间保存特权状态,以防后期无法获取二进制文件此选项至少需要以下类型中的一个分支:any, any_call, any_ret, ind_call, cond。可以省略特权级别,如果省略,将应用与分支过滤器关联的事件的特权级别。内核(k)和虚拟机监视器(hv)特权级别都受到权限的影响。在对多个事件进行采样时,对所有采样事件启用分支堆栈采样。所有事件的采样分支类型相同。各种过滤器必须指定为逗号分隔的列表:
--branch-filter any_ret,u,k
。请注意,此功能可能并非在所有处理器上都可用。
这些选项允许你在进行性能分析时收集关于程序执行过程中各种类型分支的信息。这对于理解程序的控制流行为和识别可能的性能瓶颈(例如,频繁的分支预测错误)非常有用。
2.17 加权采样
-W, --weight
,启用加权采样。每个样本记录一个额外的权重,可以使用权重和 local_weight 排序键显示。这目前适用于在现代 Intel CPU 上精确模式的 TSX 中止事件和某些内存事件。
在性能分析中,采样权重提供了一种衡量样本重要性的方法。例如,对于内存访问事件,样本的权重可能反映了访问的内存量。对于 TSX(Transactional Synchronization Extensions,事务同步扩展)中止事件,权重可能反映了事务在中止前执行的指令数量。
当使用加权采样时,你可以使用 perf report
中的权重和 local_weight 排序键来按照样本权重对采样数据进行排序。这可以帮助你更好地理解哪些事件对总体性能影响最大,并可能帮助你定位程序的性能瓶颈。
2.18 每线程采样
--per-thread
,使用每线程的内存映射(mmaps)。默认情况下,会创建每个 CPU 的内存映射。这个选项会覆盖默认设置,使用每个线程的内存映射。由此产生的副作用是会自动禁用继承。如果与 -a
或 -C
选项结合使用,--per-thread
会被忽略,并给出警告。
在默认情况下,perf record
会为每个 CPU 创建一个内存映射,这样它就可以捕获所有 CPU 上执行的事件。然而,有时你可能只关心特定线程的事件,这时可以使用 --per-thread
选项。注意,当使用 --per-thread
选项时,继承将被自动禁用。这意味着,如果一个线程生成一个新线程,新线程的事件将不会被记录。
另一方面,-a
选项是用来记录所有 CPU 的事件,而 -C
选项是用来在指定的 CPU 上记录事件。如果你尝试结合这两个选项和 --per-thread
选项使用,perf record
会忽略 --per-thread
选项,并给出警告。这是因为这些选项是互斥的:你不能同时记录所有 CPU 或特定 CPU 的事件,并且限制记录到特定线程的事件。
2.19 延迟测量
-D, --delay=
,启动程序后,等待 msecs(毫秒)再开始测量(-1:表示启动时禁用事件),或者仅在指定的毫秒范围内启用事件(例如 -D 10-20,30-40
表示等待 10 毫秒,然后在接下来的 10 毫秒内启用事件,再等待 10 毫秒,然后在接下来的 10 毫秒内启用事件,然后停止)。注意,延迟启用事件有助于过滤掉程序的启动阶段,这通常与后续执行非常不同。
在对程序进行性能分析时,程序的启动阶段通常与后续执行阶段有很大的不同。例如,启动阶段可能包括加载库、初始化数据结构等操作。这些操作可能会导致一大批性能事件,但这些事件并不反映程序的正常运行状态。为了避免这种情况,你可以使用 -D
或 --delay
选项来延迟开始记录事件,从而过滤掉启动阶段。
此外,--delay
选项也可以使你只在指定的时间范围内记录事件。例如,-D 10-20,30-40
选项会让 perf record
在程序启动后的第 10 到第 20 毫秒,以及第 30 到第 40 毫秒内记录事件。这样,你可以更精确地控制在什么时间进行事件记录。
2.20 中断时捕获机器状态
-I, --intr-regs
,在中断时捕获机器状态(寄存器),即对每个样本在计数器溢出时进行捕获。捕获的寄存器列表取决于架构。此选项默认关闭。可以使用它们的符号名称来选择需要采样的寄存器,例如在 x86 上,ax,si。要列出可用的寄存器,请使用 --intr-regs=\?
。要命名寄存器,传递一个逗号分隔的列表,例如 --intr-regs=ax,bx
。寄存器列表取决于架构。
perf record
的 --intr-regs
选项允许你在性能计数器溢出时(即当事件样本被采集时)捕获机器的寄存器状态。这可以帮助你更好地理解在事件发生时程序的状态。
每种架构都有其自己的寄存器集,你可以使用它们的符号名称来选择要采样的寄存器。例如,在 x86 架构上,你可能想要采样 ax
和 si
寄存器,你可以使用 --intr-regs=ax,si
选项来做到这一点。
如果你不确定你的架构有哪些寄存器,你可以使用 --intr-regs=\?
选项来列出所有可用的寄存器。这将显示你的架构下所有可以用于 --intr-regs
选项的寄存器的符号名称。
--user-regs
,类似于 -I
,但在采样时捕获用户空间寄存器。要列出可用的用户空间寄存器,请使用 --user-regs=\?
。
perf record
的 --user-regs
选项允许你在事件样本被采集时捕获用户空间的寄存器状态。这可以帮助你更好地理解在事件发生时程序在用户空间的状态。
与 --intr-regs
类似,你可以使用它们的符号名称来选择要采样的寄存器。如果你不确定你的架构有哪些用户空间寄存器,你可以使用 --user-regs=\?
选项来列出所有可用的用户空间寄存器。这将显示你的架构下所有可以用于 --user-regs
选项的用户空间寄存器的符号名称。
注意,这个选项只捕获用户空间的寄存器。如果你同时要捕获内核空间的寄存器,你需要使用 -I
或 --intr-regs
选项。
2.21 记录启动和运行时间
--running-time
,记录读取事件(:S)的运行时间和启用时间。
perf record
的 --running-time
选项允许你记录读取事件的运行时间和启用时间。"运行时间"是指事件在观察期间实际运行的时间,而"启用时间"是指事件在观察期间被启用的时间。
这个选项通常用于在性能分析中获取更精确的时间度量,尤其是在对系统进行长时间观察,或者在事件可能被频繁启用和禁用的情况下。
例如,如果你正在分析一个在长时间运行中可能会进入和退出睡眠状态的进程,那么 --running-time
选项可以帮助你理解进程实际运行和被启用的时间,从而使你可以更准确地评估其性能。
2.22 记录时钟字段的时钟ID
-k, --clockid
,设置用于 perf_event_type
记录中各种时间字段的时钟 ID。参见 clock_gettime()
。特别是支持 CLOCK_MONOTONIC
和 CLOCK_MONOTONIC_RAW
,某些事件也可能支持 CLOCK_BOOTTIME
,CLOCK_REALTIME
和 CLOCK_TAI
。
perf record
的 -k
或 --clockid
选项允许你设置用于 perf_event_type
记录中各种时间字段的时钟 ID。这个选项对于需要精确控制时间计量的性能分析非常有用。
这些时钟 ID 对应于 Linux 系统的不同类型的时钟:
CLOCK_MONOTONIC
:这是一个不可变的时钟,即使系统时间改变,它也会始终向前移动。CLOCK_MONOTONIC_RAW
:和CLOCK_MONOTONIC
类似,但它提供了对系统未经调整的原始时钟的访问。CLOCK_BOOTTIME
:包括系统休眠时间的时钟,自系统启动以来的总时间。CLOCK_REALTIME
:系统的实时时钟,可以被用户设置或者系统调整。CLOCK_TAI
:国际原子时间。
注意,不是所有的事件都支持所有类型的时钟。你需要根据你的特定需求和所处理的事件类型来选择适当的时钟。
2.23 选择 AUX 区域跟踪的快照模式
-S, --snapshot
,选择 AUX 区域跟踪的快照模式。这个选项只有在 AUX 区域跟踪事件中才有效。可选的,某些快照捕获参数可以在跟随此选项的字符串中指定:e
:在退出时获取一次最后的快照;保证在输出文件中至少有一次快照;<size>
:如果 PMU 支持,指定期望的快照大小。
在快照模式下,只有在接收到 SIGUSR2 信号和如果上面的 e
选项被给出则在退出时才会捕获跟踪数据。
perf record
的 --snapshot
选项允许你选择使用 AUX 区域的快照模式进行跟踪。在快照模式下,跟踪数据只有在接收到 SIGUSR2 信号时才会被捕获,如果给出了 e
选项,那么在退出时也会捕获。
这个选项在你希望控制何时捕获跟踪数据时非常有用。例如,你可能只对程序在特定信号发生时的状态感兴趣,或者你可能想要在程序结束时捕获一个最后的状态快照。
此外,如果你的性能监控单元(PMU)支持,你还可以使用 <size>
参数来指定期望的快照大小。这对于控制跟踪数据的量非常有用,尤其是在资源受限的环境中。
--aux-sample[=OPTIONS]
,选择 AUX 区域采样。由 -e
选项选择的事件中,至少有一个必须是 AUX 区域事件。将会创建包含来自 AUX 区域数据的其他事件的样本。可选的,可以指定样本大小,否则默认为 4KiB。
perf record
的 --aux-sample
选项允许你选择 AUX 区域采样。这意味着,当由 -e
选项选择的事件中至少有一个是 AUX 区域事件时,perf 会创建包含从 AUX 区域获取的数据的样本。
这个选项在你希望在事件样本中包含额外的上下文信息时非常有用。例如,你可以使用这个选项来跟踪特定事件发生时的内存状态,或者其他硬件或内核状态。
另外,你还可以选择指定样本大小。如果你没有指定,那么样本大小将默认为 4KiB。这对于控制采样数据的量非常有用,尤其是在资源受限的环境中。
2.24 异步模式配置
--aio[=n]
,在异步(Posix AIO)跟踪写入模式中使用 <n>
个控制块(默认值:1,最大值:4)。只有当 Perf 工具链接了提供 Posix AIO API 实现的 libc 库时,才支持异步模式。
perf record
的 --aio
选项允许你在异步(Posix AIO)跟踪写入模式中使用特定数量的控制块。Posix AIO(异步输入/输出)是一种允许程序在不阻塞主执行线程的情况下进行 I/O 操作的技术。
使用这个选项,你可以控制在异步模式下用于跟踪写入的控制块的数量。这对于优化跟踪数据的写入性能非常有用,尤其是在处理大量事件时。
要注意的是,这个选项只在 Perf 工具链接了提供 Posix AIO API 实现的 libc 库时才可用。如果你的环境不支持 Posix AIO,那么这个选项将无法使用。如果你没有指定 <n>
,那么使用的控制块数量将默认为1,最大值为4。
2.25 设置追踪线程的掩码
--affinity=mode
,根据模式值定义的策略设置跟踪读取线程的亲和性掩码:node
- 线程亲和性掩码设置为被处理的 mmap 缓冲区的 NUMA 节点 CPU 掩码;cpu
- 线程亲和性掩码设置为被处理的 mmap 缓冲区的 CPU。
perf record
的 --affinity
选项允许你设置跟踪读取线程的亲和性掩码。亲和性掩码是一个用于描述线程应该在哪些 CPU 上运行的位掩码。这个选项在你希望控制跟踪读取线程的调度行为时非常有用。
mode
参数定义了如何设置亲和性掩码:
node
:线程的亲和性掩码被设置为被处理的 mmap 缓冲区的 NUMA(非一致性内存访问)节点的 CPU 掩码。这意味着跟踪读取线程将被调度到同一 NUMA 节点的 CPU 上运行。cpu
:线程的亲和性掩码被设置为被处理的 mmap 缓冲区的 CPU。这意味着跟踪读取线程将被调度到同一 CPU 上运行。
使用这个选项,你可以优化跟踪读取线程的性能,尤其是在 NUMA 系统上。例如,你可以通过设置适当的亲和性掩码来减少跨 NUMA 节点的内存访问,从而提高性能。
2.26 指定从 mmap 数据页提取并进行输出处理的最小字节数
--mmap-flush=number
,指定从 mmap 数据页提取并进行输出处理的最小字节数。可以使用 B/K/M/G 后缀来指定数字。
允许的最大值是 mmaped 数据页大小的四分之一。
默认选项值为 1 字节,这意味着每次输出写入线程在 mmaped 缓冲区中找到一些新数据时,都会提取数据,可能进行压缩(-z)并写入输出,perf.data 或管道。
与较小的数据块相比,较大的数据块可以更有效地进行压缩,因此从减小输出大小的角度看,优先从 mmap 数据页提取较大的数据块是可取的。
另外,在某些情况下,执行较少的输出写入系统调用并且数据大小较大可能比执行更多的输出写入系统调用和数据大小较小的时间更少,从而降低运行时剖析的开销。
perf record
的 --mmap-flush
选项允许你指定从 mmap 数据页提取并进行输出处理的最小字节数。这个选项在你希望控制 mmap 数据页的处理方式时非常有用。
在默认情况下,每当输出写入线程在 mmaped 缓冲区中找到新数据时,它会立即提取这些数据,可能进行压缩,并将其写入输出。然而,这种处理方式可能不是最有效的。例如,较大的数据块可以更有效地进行压缩,而且执行更少的,但数据更大的写入系统调用可能比执行更多的,但数据更小的写入系统调用需要更少的时间。
使用这个选项,你可以优化 perf 的性能和输出大小。例如,你可以通过选择提取更大的数据块来减小输出大小,并通过减少写入系统调用的数量来降低运行时剖析的开销。
2.27 使用指定的级别 n
生成压缩的跟踪
-z, --compression-level[=n]
,使用指定的级别 n
生成压缩的跟踪(默认值:1 - 最快的压缩,22 - 最小的跟踪)。
perf record
的 -z
或 --compression-level
选项允许你生成压缩的跟踪。这个选项在你希望控制跟踪的大小和压缩时间时非常有用。
n
参数定义了压缩级别:
- 1:最快的压缩。这个级别的压缩速度最快,但生成的跟踪可能比较大。
- 22:最小的跟踪。这个级别的压缩速度最慢,但生成的跟踪最小。
你可以根据你的需要选择适当的压缩级别。例如,如果你希望尽快得到结果,你可以选择最快的压缩级别。如果你希望生成的跟踪尽可能小,你可以选择最小的跟踪级别。如果你没有指定 n
,那么压缩级别将默认为1。
2.28 perf.data文件配置
-
--switch-output[=mode]
,生成多个时间戳前缀的 perf.data 文件,根据 mode 值切换到新的文件:"signal" - 当接收到 SIGUSR2 时(默认值)或 - 当达到大小阈值时,期望 size 是一个带有附加单位字符的数字 - B/K/M/G - 当达到时间阈值时,期望 size 是一个带有附加单位字符的数字 - s/m/h/d注意:大小阈值的精度大大依赖于您的配置 - 您的环形缓冲区的数量和大小(-m)。对于较大的大小(如 >5M),它通常更精确,对于较低的值,期望不同的大小。
一个可能的用例是,给定一个外部事件,切分 perf.data 文件,然后处理,可能通过 perf 脚本,决定是否保留该特定的 perf.data 快照。
暗示 --timestamp-filename, --no-buildid 和 --no-buildid-cache。后两者的原因是为了减少数据文件切换的开销。您仍然可以使用以下命令开启它们:
--switch-output --no-no-buildid --no-no-buildid-cache
-
--switch-output-event
,将导致切换 perf.data 文件的事件,自动选择 --switch-output=signal,结果与内部侧带线程也向主线程发送 SIGUSR2 类似。使用与 --event 相同的语法,只是不会被记录,只用于在 --switch-output 事件被单独的侧带线程处理后尽快切换 perf.data 文件。
这个侧带线程也用于其他目的,比如处理 PERF_RECORD_BPF_EVENT 记录,向内核请求额外的 BPF 信息等。
-
--switch-max-files=N
,在使用 --switch-output 旋转 perf.data 时,只保留 N 个文件。
perf record
的 --switch-output
选项允许你生成多个 perf.data 文件,每当满足特定条件(收到特定信号、达到大小阈值或时间阈值)时,就会切换到新文件。这个选项非常适用于在给定外部事件的情况下,切分 perf.data 文件,并决定是否保留特定的 perf.data 快照。
同时,--switch-output-event
选项让你可以指定导致切换 perf.data 文件的事件,这对于需要在特定事件发生后切换记录文件的情况非常有用。
--switch-max-files
选项让你可以在旋转 perf.data 文件时,控制保留的文件数量。
2.29 只运行命令,不产生实际效果
--dry-run
,解析选项后退出。--dry-run
可用于检测命令行选项中的错误。
如果配置文件中的 llvm.dump-obj
设置为 true
,则 perf record --dry-run -e
可以作为 BPF 脚本编译器。
perf record
的 --dry-run
选项允许你在真正运行命令之前检查命令行选项是否有误。当你不确定某个选项的用法或者你正在编写一个复杂的 perf record
命令时,这个选项非常有用。
此外,当配置文件中的 llvm.dump-obj
设置为 true
时, perf record --dry-run -e
可以作为 BPF(Berkeley Packet Filter)脚本编译器使用。BPF 是一种在内核中运行的程序,它可以用于网络包过滤、系统调用跟踪等。这个选项可以让你在运行 BPF 脚本之前检查脚本是否有误。
2.30 收集和合成指定类型的事件
这个选项用于收集和合成指定类型的事件(用逗号分隔)。请注意,此选项控制的是从 /proc
文件系统进行的合成,该文件系统表示预先存在的线程的任务状态。
无论在此选项中做何选择,内核(和一些其他)事件都会被记录。例如,--synth=no
将会为内核和模块有 MMAP 事件。可用的类型包括:
task
- 为每个任务合成 FORK 和 COMM 事件mmap
- 为每个进程合成 MMAP 事件(隐含了 task)cgroup
- 为每个 cgroup 合成 CGROUP 事件all
- 合成所有事件(默认)no
- 不合成上述任何事件
例如,如果你想对一个程序进行性能分析,可能会使用以下命令:
bash
perf record --synth=task,mmap ./your_program
这个命令将会在你的程序运行时,捕获所有的 task
和 mmap
类型的事件,这些事件会被记录到一个名为 perf.data
的文件中。然后,你可以使用 perf report
命令查看这些事件的统计信息,以帮助你理解程序的性能瓶颈。
2.31 覆写旧数据
此选项使所有事件使用可覆写的环形缓冲区。可覆写的环形缓冲区的工作方式类似于飞行记录器:当它满时,内核会覆盖最旧的记录,因此这些记录将永远不会进入 perf.data 文件。
当使用 --overwrite
和 --switch-output
时,perf 会记录和丢弃事件,直到它接收到一个信号,意味着检测到了某些不寻常的情况,这值得获取最新事件的快照,即在那一刻适合在环形缓冲区中的事件。
overwrite 属性也可以使用配置项为事件设置或取消。例如:cycles/overwrite/
和 instructions/no-overwrite/
。隐含了 --tail-synthesize
。
例如,如果你想在程序运行过程中记录性能事件,但是你的存储空间有限,你可能会使用以下命令:
yacas
perf record --overwrite ./your_program
这个命令将会在你的程序运行时,捕获所有的性能事件,但是它将只保留最新的事件,而旧的事件将会被丢弃。这样,即使你的程序运行很长时间,也不会占用过多的存储空间。
2.32 动态控制性能测量开关
--control=fifo:ctl-fifo[,ack-fifo]
, --control=fd:ctl-fd[,ack-fd]
这两个选项让你在 perf record
执行的过程中动态地控制性能测量。它们都会打开并使用 ctl-fifo / ack-fifo
作为 ctl-fd / ack-fd
。在 ctl-fd
描述符上监听以控制测量的命令。
可用的命令有:enable
(启用事件)、disable
(禁用事件)、enable name
(启用事件名)、disable name
(禁用事件名)、snapshot
(AUX区域跟踪快照)、stop
(停止perf record)、ping
,以及 evlist [-v|-g|-F]
(显示所有事件)。
测量可以使用 --delay=-1
选项在事件被禁用时开始。可以选择向 ack-fd
描述符发送控制命令完成(ack\n)以与控制过程同步。
以下是一个bash shell脚本的例子,用于在测量过程中启用和禁用事件:
bash
#!/bin/bash
ctl_dir=/tmp/
ctl_fifo=${ctl_dir}perf_ctl.fifo
test -p ${ctl_fifo} && unlink ${ctl_fifo}
mkfifo ${ctl_fifo}
exec {ctl_fd}<>${ctl_fifo}
ctl_ack_fifo=${ctl_dir}perf_ctl_ack.fifo
test -p ${ctl_ack_fifo} && unlink ${ctl_ack_fifo}
mkfifo ${ctl_ack_fifo}
exec {ctl_fd_ack}<>${ctl_ack_fifo}
perf record -D -1 -e cpu-cycles -a \
--control fd:${ctl_fd},${ctl_fd_ack} \
-- sleep 30 &
perf_pid=$!
sleep 5 && echo 'enable' >&${ctl_fd} && read -u ${ctl_fd_ack} e1 && echo "enabled(${e1})"
sleep 10 && echo 'disable' >&${ctl_fd} && read -u ${ctl_fd_ack} d1 && echo "disabled(${d1})"
exec {ctl_fd_ack}>&-
unlink ${ctl_ack_fifo}
exec {ctl_fd}>&-
unlink ${ctl_fifo}
wait -n ${perf_pid}
exit $?
这个脚本首先创建两个 FIFO 文件,然后开始 perf 的记录,但是延迟了所有事件的启用(使用 -D -1
选项)。然后,脚本在 5 秒后启用事件,并在 10 秒后禁用事件。在每次操作后,脚本都会读取确认消息,确认操作已成功完成。最后,脚本清理了所有创建的资源并等待 perf 进程结束。
2.33 使用并行线程进行数据处理
--threads=<spec>
, 此选项允许将收集的跟踪数据写入多个数据文件,使用并行线程进行处理。 <spec>
值可以是用户定义的掩码列表。通过冒号分隔的掩码定义了由线程监视的CPU以及该线程的亲和性掩码,它们之间用斜线分隔:
<cpus mask 1>/<affinity mask 1>:<cpus mask 2>/<affinity mask 2>:...
CPU或亲和性掩码不能与其他相应的掩码重叠。无效的CPU将被忽略,但是不允许只包含无效CPU的掩码。
例如,用户可以像下面这样指定:0,2-4/2-4:1,5-7/5-7
这指定了由两个线程组成的并行线程布局,第一个线程监视CPU 0和2-4,亲和性掩码为2-4,第二个监视CPU 1和5-7,亲和性掩码为5-7。
<spec>
值也可以是表示预定义并行线程布局的字符串:
cpu
- 为每个监视的cpu创建新的数据流线程core
- 创建新线程以监视按核心分组的CPUpackage
- 创建新线程以监视按包分组的CPUnuma
- 创建新线程以监视按NUMA域分组的CPU
预定义的布局可以在具有大量CPU的系统上使用,以避免生成多个每个CPU的流线程,但仍然能避免在数据目录文件中丢失事件。没有指定或空值的选项默认为CPU布局。由选项值定义或提供的掩码会通过-C
选项提供的掩码进行过滤。
2.34 使用 BPF 启用 off-cpu 分析
--off-cpu
,此选项使用 BPF 启用 off-cpu 分析。BPF 程序将收集带有(用户)堆栈跟踪的任务调度信息,并将它们保存为名为 "offcpu-time" 的软件事件的样本数据。样本周期将以纳秒为单位记录任务休眠的时间。
请注意,目前,BPF 只能使用帧指针("fp")收集堆栈跟踪。因此,未使用帧指针构建的应用程序可能会看到错误的地址。
3.Inter混合平台支持
详细内容可以看linux之perf(4)stat统计中有关于混合异构CPU的介绍。
PU以及该线程的亲和性掩码,它们之间用斜线分隔:
<cpus mask 1>/<affinity mask 1>:<cpus mask 2>/<affinity mask 2>:...
CPU或亲和性掩码不能与其他相应的掩码重叠。无效的CPU将被忽略,但是不允许只包含无效CPU的掩码。
例如,用户可以像下面这样指定:0,2-4/2-4:1,5-7/5-7
这指定了由两个线程组成的并行线程布局,第一个线程监视CPU 0和2-4,亲和性掩码为2-4,第二个监视CPU 1和5-7,亲和性掩码为5-7。
<spec>
值也可以是表示预定义并行线程布局的字符串:
cpu
- 为每个监视的cpu创建新的数据流线程core
- 创建新线程以监视按核心分组的CPUpackage
- 创建新线程以监视按包分组的CPUnuma
- 创建新线程以监视按NUMA域分组的CPU
预定义的布局可以在具有大量CPU的系统上使用,以避免生成多个每个CPU的流线程,但仍然能避免在数据目录文件中丢失事件。没有指定或空值的选项默认为CPU布局。由选项值定义或提供的掩码会通过-C
选项提供的掩码进行过滤。
2.34 使用 BPF 启用 off-cpu 分析
--off-cpu
,此选项使用 BPF 启用 off-cpu 分析。BPF 程序将收集带有(用户)堆栈跟踪的任务调度信息,并将它们保存为名为 "offcpu-time" 的软件事件的样本数据。样本周期将以纳秒为单位记录任务休眠的时间。
请注意,目前,BPF 只能使用帧指针("fp")收集堆栈跟踪。因此,未使用帧指针构建的应用程序可能会看到错误的地址。
3.Inter混合平台支持
详细内容可以看linux之perf(4)stat统计中有关于混合异构CPU的介绍。