【问题标题】:Enable/disable perf event collection programmatically以编程方式启用/禁用 perf 事件收集
【发布时间】:2022-01-15 17:28:45
【问题描述】:

我在 Ubuntu 20.04 上使用 perf 进行分析(尽管我可以使用任何其他免费工具)。它允许在 CLI 中传递延迟,以便在程序启动后的特定时间后开始事件收集。但是,这个时间变化很大(1000 秒中有 20 秒),而且还有一些我对尾部计算也不感兴趣。

所以最好从我的程序中调用一些 API 来为我感兴趣的代码片段启动 perf 事件收集,然后在代码完成后停止收集。

在循环中运行代码并不是一个真正的选择,因为有大约 30 秒的初始化阶段和 10 秒的测量阶段,我只对后者感兴趣。

【问题讨论】:

标签: c++ linux api profiling perf


【解决方案1】:

在被分析的程序(或控制进程)和 perf 进程之间有一个进程间通信机制来实现这一点:使用 --control 选项,格式为 --control=fifo:ctl-fifo[,ack-fifo]--control=fd:ctl-fd[,ack-fd],如perf-stat(1) 联机帮助页。此选项指定一对 FIFO 文件(命名管道)的路径名或一对文件描述符。第一个文件用于发出命令以启用或禁用正在侦听同一文件的任何 perf 进程中的所有事件。第二个文件是可选的,用于在实际执行命令时检查 perf。

手册页中有一个示例显示如何使用此选项从 bash 脚本控制 perf 进程,您可以轻松地将其转换为 C/C++:

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}

这首先检查文件/tmp/perf_ctl.fifo,如果存在,是否是命名管道,然后才将其删除。如果文件不存在,这不是问题,但如果它存在并且它不是命名管道,则不应删除该文件,mkfifo 应该会失败。 mkfifo 创建一个路径名为 /tmp/perf_ctl.fifo 的命名管道。然后下一个命令以读/写权限打开文件并将文件描述符分配给ctl_fd。等效的系统调用是fstatunlinkmkfifoopen。请注意,命名管道将由 shell 脚本(控制进程)或正在分析的进程写入,并将从 perf 进程中读取。对第二个命名管道 ctl_fd_ack 重复相同的命令,这将用于接收来自 perf 的确认。

perf stat -D -1 -e cpu-cycles -a -I 1000       \
          --control fd:${ctl_fd},${ctl_fd_ack} \
          -- sleep 30 &
perf_pid=$!

这会fork当前进程并在继承相同文件描述符的子进程中运行perf stat程序。 -D -1 选项告诉 perf 从禁用所有事件开始。您可能需要按如下方式更改性能选项:

perf stat -D -1 -e <your event list> --control fd:${ctl_fd},${ctl_fd_ack} -p pid

在这种情况下,要分析的程序与控制进程相同,因此请告诉 perf 使用 -p 分析您已经运行的程序。等效的系统调用是fork,后跟子进程中的execv

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})"

示例脚本休眠大约 5 秒,将“启用”写入ctl_fd 管道,然后检查来自 perf 的响应以确保事件已启用,然后在大约 10 秒后继续禁用事件。等效的系统调用是writeread

脚本的其余部分删除文件描述符和管道文件。

现在把它们放在一起,你的程序应该是这样的:

/* PART 1
Initialization code.
*/

/* PART 2
Create named pipes and fds.
Fork perf with disabled events.
perf is running now but nothing is being measured.
You can redirect perf output to a file if you wish.
*/

/* PART 3
Enable events.
*/

/* PART 4
The code you want to profile goes here.
*/

/* PART 5
Disable events.
perf is still running but nothing is being measured.
*/

/* PART 6
Cleanup.
Let this process terminate, which would cause the perf process to terminate as well.
Alternatively, use `kill(pid, SIGINT)` to gracefully kill perf.
perf stat outputs the results when it terminates.
*/

【讨论】:

    猜你喜欢
    • 2020-12-18
    • 1970-01-01
    • 1970-01-01
    • 2011-03-04
    • 2013-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-25
    相关资源
    最近更新 更多