首页 > 系统相关 >使用 perf probe测量Linux用户空间代码的执行时间

使用 perf probe测量Linux用户空间代码的执行时间

时间:2024-08-28 08:57:39浏览次数:13  
标签:even evenodd perf python probe common Linux

1 Linux perf 简介

perf 是 Linux 内核自带的一个强大的性能分析工具,它能够深入到内核和用户空间,提供丰富的性能计数器和事件跟踪功能,帮助开发者和系统管理员精确地定位系统性能瓶颈。

image

1.1 perf 的主要功能:

  • 性能事件采样: 可以采样各种硬件性能事件,如 CPU 周期、缓存命中率、指令退休率等,从而分析程序在 CPU 上的执行情况。
  • 软件事件跟踪: 可以跟踪内核和用户空间的函数调用、系统调用等软件事件,分析程序的执行流程和函数调用关系。
  • 性能计数器: 提供了大量的硬件性能计数器,可以用来分析 CPU、内存、缓存等硬件资源的使用情况。
  • 火焰图生成: 可以生成火焰图,直观地展示程序的调用栈,快速定位性能热点。
  • 实时监控: 可以实时监控系统的性能指标,帮助快速发现性能问题。

1.2 perf 的工作原理:

perf 主要通过以下方式来收集性能数据:

  • 硬件性能计数器: 利用 CPU 内置的性能计数器,直接获取硬件的性能数据。
  • 软件事件跟踪: 在内核和用户空间插入探针,跟踪软件事件的发生。
  • 内核协作: perf 与内核紧密协作,通过内核接口获取性能数据。

1.3 perf 的常用命令:

  • perf list: 列出所有可用的性能事件。
  • perf stat: 统计性能事件的计数。
  • perf record: 记录性能数据。
  • perf report: 分析记录的数据,生成报告。
  • perf top: 实时显示占用 CPU 时间最多的函数。
  • perf trace: 追踪系统调用和软中断。

1.4 perf 的应用场景:

  • 定位性能瓶颈: 通过分析性能数据,找出程序中消耗时间最长的部分。
  • 优化代码: 根据性能分析结果,有针对性地优化代码。
  • 分析系统问题: 分析系统性能问题,如 CPU 负载过高、内存泄漏等。
  • 调优内核参数: 调整内核参数,提高系统性能。

1.5 perf 的优势:

  • 功能强大: 提供了丰富的性能分析功能。
  • 灵活易用: 命令行界面简单易学。
  • 开源免费: 作为 Linux 内核的一部分,完全免费。
  • 社区活跃: 有一个庞大的社区,提供丰富的文档和支持。

2 使用 perf probe测量Linux用户空间代码的执行时间

2.1 测量的示例程序evenodd.c

#include <stdio.h>
#include <unistd.h>

void even(void)
{
     printf("it is even\n");
}

void odd(void)
{
     printf("it is odd\n");
}
int main()
{
     int i;
     for (i = 0; ;i++) {
          usleep(500);
          if (i % 2)
               odd();
          else
               even();
     }
}

参考资料

2.2 使用调试符号编译 even odd:

# gcc -o -g evenodd evenodd.c
# perf probe --line even -x evenodd
<even@/root/code/evenodd.c:0>
      0  void even(void)
         {
      2       printf("it is even\n");
      3  }

         void odd(void)
         {

2.3 添加探针

在 even() 函数的开头添加 perf 探针,请运行以下命令:

# perf probe -x evenodd 'even'

要获取给定函数的执行时间,我们需要在函数的最后一行添加探针。如 perf probe -line 示例所示,是第 3 行。下面的命令在 evenondd 二进制文件的函数 event() 的第 3 行添加了名为 even_end event 的探针。

# perf probe -x evenodd 'even_end=even:3'

开始运行evenodd应用程序后,运行以下命令记录 even() 执行 10 秒的进入和退出探针:

# perf record -e probe_evenodd:even -e probe_evenodd:even_end -a sleep 10

记录结束后,可以使用以下命令打印跟踪结果:

# perf script
         evenodd 2342328 [034] 1232877.416865:     probe_evenodd:even: (4006c4)
         evenodd 2342328 [034] 1232877.416875: probe_evenodd:even_end: (4006d8)
         evenodd 2342328 [034] 1232877.417990:     probe_evenodd:even: (4006c4)
         evenodd 2342328 [034] 1232877.417996: probe_evenodd:even_end: (4006d8)
         evenodd 2342328 [034] 1232877.419109:     probe_evenodd:even: (4006c4)
...

2.4 python分析

还可以使用 perf python脚本自动计算执行时间。捕获这两个事件的跟踪后,以下命令将生成名为 perf-script.py 的 python 脚本框架:

# perf script -g python

然后编辑探测处理程序,计算执行时间:

# perf script event handlers, generated by perf script -g python
# Licensed under the terms of the GNU GPL License version 2

# The common_* event handler fields are the most useful fields common to
# all events.  They don't necessarily correspond to the 'common_*' fields
# in the format files.  Those fields not available as handler params can
# be retrieved using Python functions of the form common_*(context).
# See the perf-script-python Documentation for the list of available functions.

from __future__ import print_function

import os
import sys

sys.path.append(os.environ['PERF_EXEC_PATH'] + \
        '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')

from perf_trace_context import *
from Core import *


def trace_begin():
        print("in trace_begin")

def trace_end():
        print("in trace_end")

start=0
def probe_evenodd__even(event_name, context, common_cpu, common_secs, common_nsecs, common_pid, common_comm, common_callchain, __probe_ip, perf_sample_dict):
    global start
    start=(common_secs * 1000000000) + common_nsecs

def probe_evenodd__even_end(event_name, context, common_cpu, common_secs, common_nsecs, common_pid, common_comm, common_callchain, __probe_ip, perf_sample_dict):

    now=common_secs * 1000000000 + common_nsecs
    duration=now - start
    print("even runtime: " + str(duration) + " ns")

def trace_unhandled(event_name, context, event_fields_dict, perf_sample_dict):
                print(get_dict_as_string(event_fields_dict))
                print('Sample: {'+get_dict_as_string(perf_sample_dict['sample'], ', ')+'}')

def print_header(event_name, cpu, secs, nsecs, pid, comm):
        print("%-20s %5u %05u.%09u %8u %-20s " % \
        (event_name, cpu, secs, nsecs, pid, comm), end="")

def get_dict_as_string(a_dict, delimiter=' '):
        return delimiter.join(['%s=%s'%(k,str(v))for k,v in sorted(a_dict.items())])

然后,运行以下命令,就可以打印出函数 even 的执行时间:

# perf script -s perf-script.py  | tail
even runtime: 6540 ns
even runtime: 7080 ns
even runtime: 6770 ns
even runtime: 7220 ns
even runtime: 6850 ns
even runtime: 6390 ns
even runtime: 6910 ns
even runtime: 6760 ns
even runtime: 7460 ns
in trace_end

标签:even,evenodd,perf,python,probe,common,Linux
From: https://www.cnblogs.com/testing-/p/18383538

相关文章

  • linux 常规操作术语
    manls===>查看ls后面可以接哪些参数aliasif="ifconfig"===》给ifconfig取个别名叫做ifunaliasif===》取消if这个别名vim命令:编辑文件:vim+文件名编辑内容步骤:1.进入界面后按下字母键:i(i代表的是insert插入的意思)从命令模式切换到编辑模式2.输入完成......
  • Linux firewalld防火墙学习总结
    实践环境CentOS-7-x86_64-DVD-2009简介Firewalld是一种简单的、有状态的、基于区域(zone-based)的防火墙。策略和区域用于组织防火墙规则。网络在逻辑上被划分为多个区域,它们之间的流量可以通过策略进行管理。查看防火墙状态#servicefirewalldstatus或者#systemctls......
  • Linux网络:TCP & UDP socket
    Linux网络:TCP&UDPsocketsocket套接字sockaddr网络字节序IP地址转换bzeroUDPsocketsocketbindrecvfromsendtoTCPsocketsocketbindlistenconnectacceptsendrecv本博客讲解Linux下的TCP和UDP套接字编程。无论是创建套接字、绑定地址,还是发送和接收数据,......
  • Linux操作系统Lvm扩容(新加盘)
    在Linux操作系统中,使用LVM(逻辑卷管理器)可以轻松地扩展磁盘容量。下面是一些步骤来扩展LVM新加盘的容量:确定新加盘的设备名称,例如/dev/sdb使用fdisk命令创建一个新的分区(根据扩容目标得文件系统格式进行格式化)sudofdisk/dev/sdb连续按下n键,然后选择主分区(p),接着......
  • Linux基础软件-dns(二)
    作者介绍:简历上没有一个精通的运维工程师。希望大家多多关注作者,下面的思维导图也是预计更新的内容和当前进度(不定时更新)。Linux进阶部分又分了很多小的部分,我们刚讲完了Linux日常运维。讲的那些东西都算是系统自带的,但是Linux作为一个服务器操作系统,肯定是要安装运行软件......
  • Linux基础虚拟化实验
    常见虚拟化技术虚拟化主要厂商及产品介绍:系列PC/服务器版代表VMwareVMwareworkstation、vSphereMicrosoftVirtualPC、Hyper-VRedHatKVM、RHEVcitrixXenoracleOracleVMVIrtualBox       虚拟化与云计算的关系:虚拟化:一种技术,顾名......
  • Linux 属主属组设置和文件类型
    今天给伙伴们分享一下Linux属主属组设置和文件类型,希望看了有所收获。我是公众号「想吃西红柿」「云原生运维实战派」作者,对云原生运维感兴趣,也保持时刻学习,后续会分享工作中用到的运维技术,在运维的路上得到支持和共同进步!如果伙伴们看了文档觉得有用,欢迎大家关注我的公......
  • Linux——网络(3)
    一、服务器1、单循环服务器        服务器在同一时刻只能响应一个客户端的请求2、并发服务器模型        服务器在同一时刻可以响应多个客户端的请求3、TCP和UDP        UDP: 无连接        TCP:  有连接           ......
  • linux系统内存不足时, 系统杀死程序 哪儿查看日记
    下面是由ai回答的:当Linux系统内存不足时,系统可能会通过OOMkiller(Out-Of-Memorykiller)机制自动杀死一些进程以释放内存。要查看因内存不足而被系统杀死的程序,可以通过查看系统日志来获取相关信息。根据搜索结果,以下是一些常用的方法来查看系统日志中的相关记录:使用dmesg......
  • 非常全的Linux常用命令
    Linux常用命令 系统信息 arch显示机器的处理器架构uname-m显示机器的处理器架构uname-r显示正在使用的内核版本 dmidecode-q显示硬件系统部件-(SMBIOS/DMI) hdparm-i/dev/hda罗列一个磁盘的架构特性 hdparm-tT/dev/sda在磁盘上执行测试性读取操作 cat/p......