重定向性能输出

Redirect perf ouput

我正在编写性能监控脚本来监控应用程序。在此脚本中,调用 perf,然后应用程序等待一段时间,然后终止 perf 进程并收集 perf 信息以及其他非 perf 指标。我通过调用 运行 perf 命令:

os.popen('perf stat -d -p ' + pid_executable + ' -o DATA/perf_stat.txt &')

我后来终止了这个 perf 调用:

os.popen('kill -INT ' + pid_perf)

-o选项是将常规的stdout输出到一个文件中。不幸的是,当 kill 被调用时 none 的信息被收集。输出如下:

# started on Tue Oct  5 22:28:43 2021


 Performance counter stats for process id '8056':

     <not counted>      task-clock                                                  
     <not counted>      context-switches                                            
     <not counted>      cpu-migrations                                              
     <not counted>      page-faults                                                 
     <not counted>      cycles                                                      
     <not counted>      instructions                                                
     <not counted>      branches                                                    
     <not counted>      branch-misses                                               
     <not counted>      L1-dcache-loads                                             
     <not counted>      L1-dcache-load-misses                                       
     <not counted>      LLC-loads                                                   
     <not counted>      LLC-load-misses                                             

       0.382097310 seconds time elapsed

Some events weren't counted. Try disabling the NMI watchdog:
    echo 0 > /proc/sys/kernel/nmi_watchdog
    perf stat ...
    echo 1 > /proc/sys/kernel/nmi_watchdog

我的性能版本是: perf version 3.10.0-957.12.1.el7.x86_64.debug

我曾尝试使用环境变量来保存输出并使用管道、tee> 进行重定向,但这产生了类似的结果。我无权访问 sudo,并且正常的 --timeout 选项不可用。在 Python 脚本之外正常调用时,Perf 也能正常工作。

信息被写入文件,只是没有被收集。我如何收集这些信息以便正确收集?

看看 this 之前 post 的回答。 本质上,最好的处理方式是以“Pythonic”方式,而不是让 popen 来处理。 所以在你的情况下,你想做这样的事情:

from subprocess import PIPE, Popen

command = f"perf stat -d -p {pid_executable}"
with Popen(command, stdout=PIPE, stderr=None, shell=True) as process:
    output = process.communicate()[0].decode("utf-8")
    with open("perf_stat.txt", "w") as f:
        f.write(output)

TBH 我没有测试就写了这篇文章,但它应该按照它写的方式工作

可能您附加到的进程在 perf 的时间间隔内没有生成任何事件是 运行。例如,如果它睡着了,再也没有醒来。

在这种情况下,对于 perf 甚至没有记录 start 点的每个事件,您都会得到 <not counted>,例如没有上下文切换到进程。 (perf stat 仍然可以为事件记录和打印 0,因此 <not counted> 的含义比 0 多。尽管对于 task-clock 或循环之类的事件,它本质上是同义词因为当进程 运行.)

时,这些事件不可能不计算任何计数或时间

无论 perf 是输出到终端并使用 control-C 终止,还是使用 -o 输出到文件,这一切都适用。 (刚刚在我的桌面上用铬进程的 PID 测试了它,在我离开 perf 运行 的 2 秒内显然没有做任何事情。)

但是无论如何,您应该将 <not collected> 视为 0,或者表明您的采样时间不够长,没有发现任何有趣的东西。