是的,perf record 的 intel_pt 模式与软件(cpu 时钟)或硬件(周期)事件不同,sampling (statistical) profiling 也不同。采样每秒有 4000 个 current EIP 样本,并为您提供代码执行的基本不精确视图。 intel_pt 是基于硬件的跟踪技术,它会生成有关每个控制流指令的大量数据(在默认 perf intel_pt 模式下),允许重建完整的控制流,但它具有更大的开销。因此,英特尔 PT 的频率与程序代码每秒执行的调用、分支和返回的数量相同(数以百万计)。
通过对硬件事件进行采样,perf record 将要求硬件 PMU 对 CPU 周期等事件进行计数,并在例如 200 万次此类事件后生成溢出中断。在这种中断上,内核中的 perf_events 子系统将记录当前 OS 时间戳、当前线程的 pid/tid、指向环形缓冲区的 EIP 指令指针并重置 PMU 计数器以获得新值。 perf 子系统确实通过自动调整该值来限制最大中断频率,并且-F 选项可用于更改所需的中断频率。当环形缓冲区(大约几兆字节大小)被填满时,perf 用户空间工具会将其内容转储到perf.data 文件中,您可以使用perf script 或perf script -D 查看原始数据。或者只是用perf report 制作直方图(按照该 EIP 指令地址上出现中断的频率对 EIP 进行排序,这与该代码所花费的时间成正比)。这种模式每秒有大约 4000 个线程执行事件 (perf report --header | grep sample_freq),每个样本 48 字节,即每秒 192 KB。开销基本够低,只是采样不准确。
perf wiki 有单独的页面用于英特尔处理器跟踪 (intel_pt) - https://perf.wiki.kernel.org/index.php/Perf_tools_support_for_Intel%C2%AE_Processor_Trace
控制流跟踪不同于其他类型的性能分析和调试。它提供有关程序中采用的分支的细粒度信息,但这意味着可能存在大量跟踪数据。如此庞大的跟踪数据量带来了许多挑战,但它提出了一个核心问题:如何减少需要捕获的跟踪数据量。这与通常进行性能分析的方式相反。您需要先创建一个适合跟踪的测试用例,而不是获取一个测试用例并对其进行跟踪。
因此,intel_pt 是集成到 CPU 硬件中的跟踪(记录)模块,当启用时,它将根据使用的设置生成“每 CPU 每秒数百兆字节的跟踪数据”。使用某些设置,它可能会比写入磁盘甚至 RAM(“溢出数据包”)更快地生成跟踪数据(数据包日志)。根据https://lwn.net/Articles/648154/ 文章,intel_pt 模式下的 perf_events(内核模式)只会将完整的数据包日志保存到单独的(更大?)环形缓冲区和 perf 工具(用户空间)只会定期将环形缓冲区中的数据保存到文件中以供离线使用过滤、解析和解码。 (将 aux 或 ring mmap 保存到文件中的周期与溢出中断频率选项-F 不同)然后将使用 PT 解码器将 PT 数据包日志重建为 perf 兼容的样本。日志数据量很大,overhead is 1% - 5% - 10% or more 取决于执行代码中的分支频率。
intel_pt 的文档是manpage man perf-intel-pt,长文本存储在 linux 内核源代码中
https://github.com/torvalds/linux/blob/master/tools/perf/Documentation/perf-intel-pt.txt
Intel PT 首先在 Intel Core M 和第 5 代 Intel Core 中得到支持
基于 Intel 微架构代号 Broadwell 的处理器。
跟踪数据由“性能记录”收集并存储在 perf.data 文件中。 ...跟踪数据必须被“解码”,这涉及遍历目标代码和匹配跟踪数据包。 ...解码是即时完成的。解码器以相同的格式输出样本
perf 硬件事件的输出样本,例如“指令”
或“分支”事件已被记录。目前有 3 个工具支持这一点:
“性能脚本”、“性能报告”和“性能注入”。 ... Intel PT 的主要区别在于解码器可以确定
软件执行的确切流程。英特尔 PT 可用于了解原因
以及软件是如何达到某一点或以某种方式运行的。 ... Intel PT 的一个限制是它会产生大量的跟踪数据
(每个核心每秒数百兆字节)解码需要很长时间
默认情况下perf record -e intel_pt// 与-e intel_pt/tsc=1,noretcomp=0/ 相同。 manpage man perf-intel-pt 的 config terms 部分说明了默认设置:
tsc 始终支持。
生成 TSC 时间戳数据包以提供时间信息。在某些情况下,可以在没有时间信息的情况下进行解码,例如不与可执行内存映射重叠的每线程上下文。
noretcomp 始终支持。禁用“返回压缩”所以提示
当函数返回时产生数据包。导致更多的数据包
生成,但可能会使解码更可靠。
pt 指定启用分支配置项的传递。
branch 启用分支跟踪。默认启用分支跟踪
为了表示软件控制流,会生成“分支”样本。
默认情况下,每个分支都会合成一个分支样本。
正如它所说,默认模式下的 intel_pt 用于生成控制流日志,通过要求硬件为每个控制流指令(如调用、分支、返回)生成日志包,并添加时间戳以使 pt 日志与某些服务性能同步示例(如 exec 或 mmap 以查找正在加载到内存中的实际代码)。它尝试生成的不是太多,例如 [单个位用于每个条件分支 (tnt)](https://conference.hitb.org/hitbsecconf2017ams/materials/D1T1 - Richard Johnson - Harnessing Intel Processor Trace on Windows for Vulnerability Discovery.pdf#page=12) 和 several bytes per indirect branch ,但许多程序每秒有数亿个分支。
perf + intel_pt 上的一些有用且简短的幻灯片:
更新: 虽然 intel pt 跟踪日志具有完整跟踪(每个分支/调用/返回都有数据包),但 perf report 确实运行从 pt 日志到样本集的转换,就像在经典 perf 中一样.data,并且样本集中有采样率。这是使用perf report 的--itrace 选项配置的(iNNTT,其中 NN 是数量,TT 是类型 - i/t/us/ns,如 described in man page of perf-report:
--itrace
Options for decoding instruction tracing data. The options are:
i synthesize instructions events
g synthesize a call chain (use with i or x)
The default is all events i.e. the same as --itrace=ibxwpe,
In addition, the period (default 100000, ...)
for instructions events can be specified in units of:
i instructions
t ticks
ms milliseconds
us microseconds
ns nanoseconds (default)
因此,默认情况下,perf report 似乎会以 100000 条指令的采样率将完整的跟踪日志转换为指令样本(每 10 万条指令生成 1 个 perf 样本)。它可以更改为更高的速率,但处理时间会增加。
Manpage of perf-intel-pt 给出了更多关于 itrace 选项使用的例子:
Because samples are synthesized after-the-fact, the sampling period
can be selected for reporting. e.g. sample every microsecond
sudo perf report pt_ls --itrace=i1usge
See the sections below for more information about the --itrace
option.
Beware the smaller the period, the more samples that are produced,
and the longer it takes to process them.
Also note that the coarseness of Intel PT timing information will
start to distort the statistical value of the sampling as the
sampling period becomes smaller.
To see every possible IPC value, "instructions" events can be used
e.g. --itrace=i0ns
--itrace=i10us
sets the period to 10us i.e. one instruction sample is synthesized
for each 10 microseconds of trace. Alternatives to "us" are "ms"
(milliseconds), "ns" (nanoseconds), "t" (TSC ticks) or "i"
(instructions).
For Intel PT, the default period is 100us.
Setting it to a zero period means "as often as possible".
In the case of Intel PT that is the same as a period of 1 and a unit
of instructions (i.e. --itrace=i1i).
http://halobates.de/blog/p/410 有一些额外的复杂转换示例:
perf script --ns --itrace=cr
记录程序执行并显示函数调用图。
perf 脚本默认“采样”数据(每次只转储一个样本)
100 微秒)。这可以使用 --itrace 选项进行配置(参见
以下参考)
perf script --itrace=i0ns --ns -F time,pid,comm,sym,symoff,insn,ip | xed -F insn: -S /proc/kallsyms -64
显示使用反汇编程序执行的每条汇编指令。
perf report --itrace=g32l64i100us --branch-history
每 100us 打印一次热路径作为调用图直方图
perf script --itrace=i100usg | stackcollapse-perf.pl > workload.folded
flamegraph.pl workloaded.folded > workload.svg
google-chrome workload.svg
从执行中生成火焰图,每 100us 采样一次