立即前往

活动

天翼云最新优惠活动,涵盖免费试用,产品折扣等,助您降本增效!
热门活动
  • 智算采购季 热销S6云服务器2核4G限时88元/年起,部分主机可加赠对象存储组合包!
  • 免费体验DeepSeek,上天翼云息壤 NEW 新老用户均可免费体验2500万Tokens,限时两周
  • 云上钜惠 HOT 爆款云主机全场特惠,更有万元锦鲤券等你来领!
  • 算力套餐 HOT 让算力触手可及
  • 天翼云脑AOne NEW 连接、保护、办公,All-in-One!
  • 一键部署Llama3大模型学习机 0代码一键部署,预装最新主流大模型Llama3与StableDiffusion
  • 中小企业应用上云专场 产品组合下单即享折上9折起,助力企业快速上云
  • 息壤高校钜惠活动 NEW 天翼云息壤杯高校AI大赛,数款产品享受线上订购超值特惠
  • 天翼云电脑专场 HOT 移动办公新选择,爆款4核8G畅享1年3.5折起,快来抢购!
  • 天翼云奖励推广计划 加入成为云推官,推荐新用户注册下单得现金奖励
免费活动
  • 免费试用中心 HOT 多款云产品免费试用,快来开启云上之旅
  • 天翼云用户体验官 NEW 您的洞察,重塑科技边界

智算服务

打造统一的产品能力,实现算网调度、训练推理、技术架构、资源管理一体化智算服务
智算云(DeepSeek专区)
科研助手
  • 算力商城
  • 应用商城
  • 开发机
  • 并行计算
算力互联调度平台
  • 应用市场
  • 算力市场
  • 算力调度推荐
一站式智算服务平台
  • 模型广场
  • 体验中心
  • 服务接入
智算一体机
  • 智算一体机
大模型
  • DeepSeek-R1-昇腾版(671B)
  • DeepSeek-R1-英伟达版(671B)
  • DeepSeek-V3-昇腾版(671B)
  • DeepSeek-R1-Distill-Llama-70B
  • DeepSeek-R1-Distill-Qwen-32B
  • Qwen2-72B-Instruct
  • StableDiffusion-V2.1
  • TeleChat-12B

应用商城

天翼云精选行业优秀合作伙伴及千余款商品,提供一站式云上应用服务
进入甄选商城进入云市场创新解决方案
办公协同
  • WPS云文档
  • 安全邮箱
  • EMM手机管家
  • 智能商业平台
财务管理
  • 工资条
  • 税务风控云
企业应用
  • 翼信息化运维服务
  • 翼视频云归档解决方案
工业能源
  • 智慧工厂_生产流程管理解决方案
  • 智慧工地
建站工具
  • SSL证书
  • 新域名服务
网络工具
  • 翼云加速
灾备迁移
  • 云管家2.0
  • 翼备份
资源管理
  • 全栈混合云敏捷版(软件)
  • 全栈混合云敏捷版(一体机)
行业应用
  • 翼电子教室
  • 翼智慧显示一体化解决方案

合作伙伴

天翼云携手合作伙伴,共创云上生态,合作共赢
天翼云生态合作中心
  • 天翼云生态合作中心
天翼云渠道合作伙伴
  • 天翼云代理渠道合作伙伴
天翼云服务合作伙伴
  • 天翼云集成商交付能力认证
天翼云应用合作伙伴
  • 天翼云云市场合作伙伴
  • 天翼云甄选商城合作伙伴
天翼云技术合作伙伴
  • 天翼云OpenAPI中心
  • 天翼云EasyCoding平台
天翼云培训认证
  • 天翼云学堂
  • 天翼云市场商学院
天翼云合作计划
  • 云汇计划
天翼云东升计划
  • 适配中心
  • 东升计划
  • 适配互认证

开发者

开发者相关功能入口汇聚
技术社区
  • 专栏文章
  • 互动问答
  • 技术视频
资源与工具
  • OpenAPI中心
开放能力
  • EasyCoding敏捷开发平台
培训与认证
  • 天翼云学堂
  • 天翼云认证
魔乐社区
  • 魔乐社区

支持与服务

为您提供全方位支持与服务,全流程技术保障,助您轻松上云,安全无忧
文档与工具
  • 文档中心
  • 新手上云
  • 自助服务
  • OpenAPI中心
定价
  • 价格计算器
  • 定价策略
基础服务
  • 售前咨询
  • 在线支持
  • 在线支持
  • 工单服务
  • 建议与反馈
  • 用户体验官
  • 服务保障
  • 客户公告
  • 会员中心
增值服务
  • 红心服务
  • 客户支持计划
  • 专家技术服务
  • 备案管家

了解天翼云

天翼云秉承央企使命,致力于成为数字经济主力军,投身科技强国伟大事业,为用户提供安全、普惠云服务
品牌介绍
  • 关于天翼云
  • 智算云
  • 天翼云4.0
  • 新闻资讯
  • 天翼云APP
基础设施
  • 全球基础设施
  • 产品能力
  • 信任中心
最佳实践
  • 精选案例
  • 超级探访
  • 云杂志
  • 分析师和白皮书
  • 天翼云·创新直播间
市场活动
  • 2025智能云生态大会
  • 2024智算云生态大会
  • 2023云生态大会
  • 2022云生态大会
  • 天翼云中国行
天翼云
  • 活动
  • 智算服务
  • 产品
  • 解决方案
  • 应用商城
  • 合作伙伴
  • 开发者
  • 支持与服务
  • 了解天翼云
      • 文档
      • 控制中心
      • 备案
      • 管理中心

      【性能】perf + 火焰图分析软件性能瓶颈

      首页 知识中心 软件开发 文章详情页

      【性能】perf + 火焰图分析软件性能瓶颈

      2025-02-26 07:20:57 阅读次数:9

      CPU,record,调用

      零、即看即用

       前提:下载flamegraph工具包

      方法一、

      第1步、监测进程

      $ sudo perf record -a --call-graph dwarf -p 667651 sleep 30

      -p 13204:监测进程号13204 (如果想监视线程则用 -t 6665 #6665为线程号)

      --call-graph:

      dwarf:表示回溯方式,perf 同时支持 3 种栈回溯方式:fp, dwarf, lbr,推荐dwarf,理由见文章末尾

      sleep 30:持续30秒。(注意sleep 前面没有--,--sleep用法是错的)

      Ctrl+c结束执行后,在当前目录下会生成采样数据perf.data.

      第2步、 解析数据

      用perf script工具对perf.data进行解析

      perf script -i perf.data &> perf.unfold

      第3步、符号进行折叠

      将perf.unfold中的符号进行折叠:

      #./stackcollapse-perf.pl perf.unfold &> perf.folded

      第4步、生成svg图

      ./flamegraph.pl perf.folded > perf-$(date +%Y%m%d-%H:%M:%S).svg

      进入flamegraph目录把下面的yourProcessName替换成你程序的名字,拷贝执行即可:

      pname=yourProcessName&&sudo perf record -a --call-graph dwarf -p $(pidof pname) sleep 30 &&perf script -i perf.data &> perf.unfold&&./stackcollapse-perf.pl perf.unfold &> perf.folded&&./flamegraph.pl perf.folded > perf-$(date +%Y%m%d-%H:%M:%S).svg

      【性能】perf + 火焰图分析软件性能瓶颈

      方法二、

      1,perf record --call-graph dwarf -p 12345

      2,perf script | FlameGraph/stackcollapse-perf.pl | FlameGraph/flamegraph.pl > process.svg

      用法三、

      使用perf采样
      1.直接使用perf启动服务
      # perf record -g ls
      --------------------------------
      2.挂接到已启动的进程
      # 使用PID监控程序
      # sudo perf record -e cpu-clock -g -p pid
      # 如果svg图出现unknown函数,使用如下
      # sudo perf record -e cpu-clock --call-graph dwarf -p pid
      # 使用程序名监控程序
      # sudo perf record -e cpu-clock -g -p `pgrep your_program`
      ------------------------------------
      第一种方式不需要root权限,第二种方式需要root权限
      使用ctrl+c中断perf进程,或者在命令最后加上参数 --sleep n (n秒后停止)
      perf record表示记录到文件,perf top直接会显示到界面
      如果record之后想直接输出结果,使用perf report即可

      一、perf 命令

      perf简介

       perf 命令(performance 的缩写),它是 Linux 系统原生提供的性能分析工具,会返回 CPU 正在执行的函数名以及调用栈(stack)。

       Perf是一个包含22种子工具的工具集,以下是最常用的5种:

      perf-list :Perf-list用来查看perf所支持的性能事件,有软件的也有硬件的。

      perf-stat

      perf-top: perf top主要用于实时分析各个函数在某个性能事件上的热度,能够快速的定位热点函数,包括应用程序函数、模块函数与内核函数,甚至能够定位到热点指令。默认的性能事件为cpu cycles。

      perf-record

      perf-report

      perf record参数

      Perf record
      记录一段时间内系统/进程的性能时间
      
      参数:
      
       -e:选择性能事件
      
       -p:待分析进程的id
      
       -t:待分析线程的id
      
       -a:分析整个系统的性能
      
       -C:只采集指定CPU数据
      
       -c:事件的采样周期
      
       -o:指定输出文件,默认为perf.data
      
       -A:以append的方式写输出文件
      
       -f:以OverWrite的方式写输出文件
      
       -g:记录函数间的调用关系

      通常,它的执行频率是 99Hz(每秒99次),如果99次都返回同一个函数名,那就说明 CPU 这一秒钟都在执行同一个函数,可能存在性能问题。

      13204是进程号

      $ sudo perf record -F 99 -p 13204 -g sleep 30
      

      上面的代码中,perf record表示记录,-F 99表示每秒99次,-p 13204是进程号,即对哪个进程进行分析,-g表示记录调用栈,sleep 30则是持续30秒。

      运行后会产生一个庞大的文本文件。如果一台服务器有16个 CPU,每秒抽样99次,持续30秒,就得到 47,520 个调用栈,长达几十万甚至上百万行。

      举例:
      
      sudo perf record -e cpu-clock -g -p 2548
      
      -g 选项是告诉perf record额外记录函数的调用关系
      
      -e cpu-clock 指perf record监控的指标为cpu周期
      
      -p 指定需要record的进程pid
       

      为了便于阅读,perf record命令可以统计每个调用栈出现的百分比,然后从高到低排列。

      
      $ sudo perf report -n --stdio
      

      【性能】perf + 火焰图分析软件性能瓶颈

      这个结果还是不易读,所以才有了火焰图。

      生成火焰图

      1、Flame Graph项目位于GitHub上

      2、可以用git将其clone下来

      我们以perf为例,看一下flamegraph的使用方法:

      1、第一步

      $sudo perf record -e cpu-clock -g -p 28591

      Ctrl+c结束执行后,在当前目录下会生成采样数据perf.data.

      2、第二步

      用perf script工具对perf.data进行解析

      perf script -i perf.data &> perf.unfold

      3、第三步

      将perf.unfold中的符号进行折叠:

      #./stackcollapse-perf.pl perf.unfold &> perf.folded

      4、最后生成svg图:

      ./flamegraph.pl perf.folded > perf.svg

      【性能】perf + 火焰图分析软件性能瓶颈

      命令例子

      3.2查看单个进程各个函数cpu使用率

      perf top -e cycles -p 3352

       

      3.3使用perf record 记录:

      perf record -e cpu-clock -p 进程号

      perf report

       

       

      3.4统计进程里最耗时函数

      perf record -e cycles –g -p 进程号

      perf report

       

       

      perf record -a -F 1000 sleep 5

       

      其中-F 1000是指定采样频率为1000次/秒

      Sleep 5 指采样5秒

       

      perf stat -e 'sched:*' -p 28135 sleep 5

      统计5秒内28135进程调度情况

      二、火焰图的含义

      火焰图是基于 perf 结果产生的 SVG 图片,用来展示 CPU 的调用栈。

      【性能】perf + 火焰图分析软件性能瓶颈

      y 轴表示调用栈,每一层都是一个函数。调用栈越深,火焰就越高,顶部就是正在执行的函数,下方都是它的父函数。

      x 轴表示抽样数,如果一个函数在 x 轴占据的宽度越宽,就表示它被抽到的次数多,即执行的时间长。注意,x 轴不代表时间,而是所有的调用栈合并后,按字母顺序排列的。

      火焰图就是看顶层的哪个函数占据的宽度最大。只要有"平顶"(plateaus),就表示该函数可能存在性能问题。

      颜色没有特殊含义,因为火焰图表示的是 CPU 的繁忙程度,所以一般选择暖色调。

      三、互动性

      火焰图是 SVG 图片,可以与用户互动。

      (1)鼠标悬浮

      火焰的每一层都会标注函数名,鼠标悬浮时会显示完整的函数名、抽样抽中的次数、占据总抽样次数的百分比。下面是一个例子。

      
      mysqld'JOIN::exec (272,959 samples, 78.34 percent)
      

      (2)点击放大

      在某一层点击,火焰图会水平放大,该层会占据所有宽度,显示详细信息。

      【性能】perf + 火焰图分析软件性能瓶颈

      左上角会同时显示"Reset Zoom",点击该链接,图片就会恢复原样。

      (3)搜索

      按下 Ctrl + F 会显示一个搜索框,用户可以输入关键词或正则表达式,所有符合条件的函数名会高亮显示。

      四、火焰图示例

      下面是一个简化的火焰图例子。

      首先,CPU 抽样得到了三个调用栈。

      
      func_c 
      func_b 
      func_a 
      start_thread 
      
      func_d 
      func_a 
      start_thread 
      
      func_d 
      func_a 
      start_thread
      

      上面代码中,start_thread是启动线程,调用了func_a。后者又调用了func_b和func_d,而func_b又调用了func_c。

      经过合并处理后,得到了下面的结果,即存在两个调用栈,第一个调用栈抽中1次,第二个抽中2次。

      
      start_thread;func_a;func_b;func_c 1 
      start_thread;func_a;func_d 2
      

      有了这个调用栈统计,火焰图工具就能生成 SVG 图片。

      【性能】perf + 火焰图分析软件性能瓶颈

      上面图片中,最顶层的函数g()占用 CPU 时间最多。d()的宽度大,但是它直接耗用 CPU 的部分很少(主要是d()内调用的e()和f()消耗)。b()和c()没有直接消耗 CPU(因为一层一层调用,最终上c()内调用的函数消耗cpu)。因此,如果要调查性能问题,首先应该调查g(),其次是i()。

      另外,从图中可知a()有两个分支b()和h(),这表明a()里面可能有一个条件语句,而b()分支消耗的 CPU 大大高于h()。

      五、局限

      两种情况下,无法画出火焰图,需要修正系统行为。

      (1)调用栈不完整

      当调用栈过深时,某些系统只返回前面的一部分(比如前10层)。

      (2)函数名缺失

      有些函数没有名字,编译器只用内存地址来表示(比如匿名函数)。

      六、Node 应用的火焰图

      Node 应用的火焰图就是对 Node 进程进行性能抽样,与其他应用的操作是一样的。

      
      $ perf record -F 99 -p `pgrep -n node` -g -- sleep 30
      

      详细的操作可以看这篇文章。

      七、浏览器的火焰图

      Chrome 浏览器可以生成页面脚本的火焰图,用来进行 CPU 分析。

      打开开发者工具,切换到 Performance 面板。然后,点击"录制"按钮,开始记录数据。这时,可以在页面进行各种操作,然后停止"录制"。

      这时,开发者工具会显示一个时间轴。它的下方就是火焰图。

      【性能】perf + 火焰图分析软件性能瓶颈

      浏览器的火焰图与标准火焰图有两点差异:它是倒置的(即调用栈最顶端的函数在最下方);x 轴是时间轴,而不是抽样次数。

      【性能】perf + 火焰图分析软件性能瓶颈

      八、参考链接

      • 火焰图的介绍论文
      • 火焰图官方主页
      • 火焰图生成工具

      九、其他性能分析工具

      vtune,gprof、oprofile、valgrind、perf。vtune perf 看不到L3cache 等硬件特性,需要vtune

      十、perf工具远比上面讲的更强大

      perf top  进程哪些函数比较耗时

      perf top 可以查看某个进程的耗时百分比分布,从而知道哪些函数比较耗时:

      (模块函数与内核函数,甚至能够定位到热点指令。默认的性能事件为cpu cycles)
      查看当前系统中的热点函数perf sched record --sleep 1 -p $PID记录进程在ls内的系统调用perf sched latency --sort max查看上一步记录的结果,以调度延迟排序

      【性能】perf + 火焰图分析软件性能瓶颈

      server_name="xsearch_leaf_kdweibocrawler"
      pid=`pidof $server_name`
      echo $pid
      perf top -p $pid
      

      perf stat

      用于输出指定程序的性能统计数据

      perf record

      perf record收集采样信息,并记录在文件中,可以离线分析。使用下面的 perf report解析收集的采样数据文件。

      打印函数调用链的性能占比:

      perf record -F 99 -p ${pid} --call-graph dwarf sleep ${采样时间}

      perf report

      perf report 主要用来分析上面perf record生成的perf.data文件。

      十一、perf命令详情 

      perf是Linux下的一款性能分析工具,能够进行函数级与指令级的热点查找。
      
      Perf List
      利用perf剖析程序性能时,需要指定当前测试的性能时间。性能事件是指在处理器或操作系统中发生的,可能影响到程序性能的硬件事件或软件事件
       

      Perf top
      实时显示系统/进程的性能统计信息
      
      常用参数
      
      -e:指定性能事件
      
      -a:显示在所有CPU上的性能统计信息
      
      -C:显示在指定CPU上的性能统计信息
      
      -p:指定进程PID
      
      -t:指定线程TID
      
      -K:隐藏内核统计信息
      
      -U:隐藏用户空间的统计信息
      
      -s:指定待解析的符号信息
      
      ‘‐G’ or‘‐‐call‐graph’ <output_type,min_percent,call_order>
      
      graph: 使用调用树,将每条调用路径进一步折叠。这种显示方式更加直观。
      
      每条调用路径的采样率为绝对值。也就是该条路径占整个采样域的比率。
      
      fractal
      
      默认选项。类似与 graph,但是每条路径前的采样率为相对值。
      
      flat
      
      不折叠各条调用
      
      选项 call_order 用以设定调用图谱的显示顺序,该选项有 2个取值,分别是
      
      callee 与caller。
      
      将该选项设为callee 时,perf按照被调用的顺序显示调用图谱,上层函数被下层函数所调用。
      
      该选项被设为caller 时,按照调用顺序显示调用图谱,即上层函数调用了下层函数路径,也不显示每条调用路径的采样率

      注: Perf top需要root权限


      Perf stat
      分析系统/进程的整体性能概况
      
      task‐clock事件表示目标任务真正占用处理器的时间,单位是毫秒。也称任务执行时间
      
      context-switches是系统发生上下文切换的次数
      
      CPU-migrations是任务从一个处理器迁往另外一个处理器的次数
      
      page-faults是内核发生缺页的次数
      
      cycles是程序消耗的处理器周期数
      
      instructions是指命令执行期间产生的处理器指令数
      
      branches是指程序在执行期间遇到的分支指令数。
      
      branch‐misses是预测错误的分支指令数。
      
      XXX seconds time elapsed系程序持续时间
      
      任务执行时间/任务持续时间大于1,那可以肯定是多核引起的
      
      参数设置:
      
      -e:选择性能事件
      
      -i:禁止子任务继承父任务的性能计数器。
      
      -r:重复执行 n 次目标程序,并给出性能指标在n 次执行中的变化范围。
      
      -n:仅输出目标程序的执行时间,而不开启任何性能计数器。
      
      -a:指定全部cpu
      
      -C:指定某个cpu
      
      -A:将给出每个处理器上相应的信息。
      
      -p:指定待分析的进程id
      
      -t:指定待分析的线程id
      
      

      Perf record
      记录一段时间内系统/进程的性能时间
      
      参数:
      
       -e:选择性能事件
      
       -p:待分析进程的id
      
       -t:待分析线程的id
      
       -a:分析整个系统的性能
      
       -C:只采集指定CPU数据
      
       -c:事件的采样周期
      
       -o:指定输出文件,默认为perf.data
      
       -A:以append的方式写输出文件
      
       -f:以OverWrite的方式写输出文件
      
       -g:记录函数间的调用关系
      
      

      Perf Report
      读取perf record生成的数据文件,并显示分析数据
      
      参数
      
      -i:输入的数据文件
      
      -v:显示每个符号的地址
      
      -d <dos>:只显示指定dos的符号
      
      -C:只显示指定comm的信息(Comm. 触发事件的进程名)
      
      -S:只考虑指定符号
      
      -U:只显示已解析的符号
      
      -g[type,min,order]:显示调用关系,具体等同于perf top命令中的-g
      
      -c:只显示指定cpu采样信息
      
      -M:以指定汇编指令风格显示
      
      –source:以汇编和source的形式进行显示
      
      -p<regex>:用指定正则表达式过滤调用函数

       

       

      例1

      # perf top -e cycles:k     #显示内核和模块中,消耗最多CPU周期的函数
      
      # perf top -e kmem:kmem_cache_alloc     #显示分配高速缓存最多的函数
      
      # perf top
      
      Samples: 1M of event 'cycles', Event count (approx.): 73891391490
           5.44%  perf              [.] 0x0000000000023256      
           4.86%  [kernel]          [k] _spin_lock              
           2.43%  [kernel]          [k] _spin_lock_bh           
           2.29%  [kernel]          [k] _spin_lock_irqsave      
           1.77%  [kernel]          [k] __d_lookup              
           1.55%  libc-2.12.so      [.] __strcmp_sse42          
           1.43%  nginx             [.] ngx_vslprintf           
           1.37%  [kernel]          [k] tcp_poll          
      第一列:符号引发的性能事件的比例,默认指占用的cpu周期比例。
      第二列:符号所在的DSO(Dynamic Shared Object),可以是应用程序、内核、动态链接库、模块。
      第三列:DSO的类型。[.]表示此符号属于用户态的ELF文件,包括可执行文件与动态链接库)。[k]表述此符号属于内核或模块。
      第四列:符号名。有些符号不能解析为函数名,只能用地址表示。

      例2

      # perf top -G         #得到调用关系图
      
      # perf top -e cycles         #指定性能事件
      
      # perf top -p 23015,32476         #查看这两个进程的cpu cycles使用情况
      
      # perf top -s comm,pid,symbol         #显示调用symbol的进程名和进程号
      
      # perf top --comms nginx,top         #仅显示属于指定进程的符号
      
      # perf top --symbols kfree         #仅显示指定的符号
      	 
      

      例3

      #  perf stat ls 
      
       Performance counter stats for 'ls':
      
                0.653782 task-clock                #    0.691 CPUs utilized          
                       0 context-switches          #    0.000 K/sec                  
                       0 CPU-migrations            #    0.000 K/sec                  
                     247 page-faults               #    0.378 M/sec                  
               1,625,426 cycles                    #    2.486 GHz                    
               1,050,293 stalled-cycles-frontend   #   64.62% frontend cycles idle   
                 838,781 stalled-cycles-backend    #   51.60% backend  cycles idle   
               1,055,735 instructions              #    0.65  insns per cycle        
                                                   #    0.99  stalled cycles per insn
                 210,587 branches                  #  322.106 M/sec                  
                  10,809 branch-misses             #    5.13% of all branches        
      
             0.000945883 seconds time elapsed
      
      	输出包括ls的执行时间,以及10个性能事件的统计。
      
      	task-clock:任务真正占用的处理器时间,单位为ms。CPUs utilized = task-clock / time elapsed,CPU的占用率。
      
      	context-switches:上下文的切换次数。
      
      	CPU-migrations:处理器迁移次数。Linux为了维持多个处理器的负载均衡,在特定条件下会将某个任务从一个CPU
      
      	迁移到另一个CPU。
      
      	page-faults:缺页异常的次数。当应用程序请求的页面尚未建立、请求的页面不在内存中,或者请求的页面虽然在内
      
      	存中,但物理地址和虚拟地址的映射关系尚未建立时,都会触发一次缺页异常。另外TLB不命中,页面访问权限不匹配
      
      	等情况也会触发缺页异常。
      
      	cycles:消耗的处理器周期数。如果把被ls使用的cpu cycles看成是一个处理器的,那么它的主频为2.486GHz。
      
      	可以用cycles / task-clock算出。
      
      	stalled-cycles-frontend:略过。
      
      	stalled-cycles-backend:略过。
      
      	instructions:执行了多少条指令。IPC为平均每个cpu cycle执行了多少条指令。
      
      	branches:遇到的分支指令数。branch-misses是预测错误的分支指令数。
      
      	   
      #  perf stat -r 10 ls > /dev/null         #执行10次程序,给出标准偏差与期望的比值
      
      #  perf stat -v ls > /dev/null         #显示更详细的信息
      
      #  perf stat -n ls > /dev/null         #只显示任务执行时间,不显示性能计数器
      
      #  perf stat -a -A ls > /dev/null         #单独给出每个CPU上的信息
      
      #  perf stat -e syscalls:sys_enter ls          #ls命令执行了多少次系统调用
      	 
      

      例4

      #  perf record -p `pgrep -d ',' nginx`      #记录nginx进程的性能数据
      
      #  perf record ls -g    #记录执行ls时的性能数据
      
      # perf record -e syscalls:sys_enter ls      #记录执行ls时的系统调用,可以知道哪些系统调用最频繁
      
      

      例5

      #   perf lock record ls      #记录
      
      #   perf lock report      #报告
      
                      Name   acquired  contended total wait (ns)   max wait (ns)   min wait (ns) 
      
       &mm->page_table_...        382          0               0               0               0 
       &mm->page_table_...         72          0               0               0               0 
                 &fs->lock         64          0               0               0               0 
               dcache_lock         62          0               0               0               0 
             vfsmount_lock         43          0               0               0               0 
       &newf->file_lock...         41          0               0               0               0 
      
      Name:内核锁的名字。
      aquired:该锁被直接获得的次数,因为没有其它内核路径占用该锁,此时不用等待。
      contended:该锁等待后获得的次数,此时被其它内核路径占用,需要等待。
      total wait:为了获得该锁,总共的等待时间。
      max wait:为了获得该锁,最大的等待时间。
      min wait:为了获得该锁,最小的等待时间。
      
      

      例6

      #  perf kmem record ls      #记录
      
      #  perf kmem stat --caller --alloc -l 20      #报告
      
      ------------------------------------------------------------------------------------------------------
       Callsite                           | Total_alloc/Per | Total_req/Per   | Hit      | Ping-pong | Frag
      ------------------------------------------------------------------------------------------------------
       perf_event_mmap+ec                 |    311296/8192  |    155952/4104  |       38 |        0 | 49.902%
       proc_reg_open+41                   |        64/64    |        40/40    |        1 |        0 | 37.500%
       __kmalloc_node+4d                  |      1024/1024  |       664/664   |        1 |        0 | 35.156%
       ext3_readdir+5bd                   |        64/64    |        48/48    |        1 |        0 | 25.000%
       load_elf_binary+8ec                |       512/512   |       392/392   |        1 |        0 | 23.438%
      
      Callsite:内核代码中调用kmalloc和kfree的地方。
      Total_alloc/Per:总共分配的内存大小,平均每次分配的内存大小。
      Total_req/Per:总共请求的内存大小,平均每次请求的内存大小。
      Hit:调用的次数。
      Ping-pong:kmalloc和kfree不被同一个CPU执行时的次数,这会导致cache效率降低。
      Frag:碎片所占的百分比,碎片 = 分配的内存 - 请求的内存,这部分是浪费的。
      有使用--alloc选项,还会看到Alloc Ptr,即所分配内存的地址。
      

      例7

      #  perf sched record sleep 10    
      
      #  perf report latency --sort max    
      
       ---------------------------------------------------------------------------------------------------------------
        Task                  |   Runtime ms  | Switches | Average delay ms | Maximum delay ms | Maximum delay at     |
       ---------------------------------------------------------------------------------------------------------------
        events/10:61          |      0.655 ms |       10 | avg:    0.045 ms | max:    0.161 ms | max at: 9804.958730 s
        sleep:11156           |      2.263 ms |        4 | avg:    0.052 ms | max:    0.118 ms | max at: 9804.865552 s
        edac-poller:1125      |      0.598 ms |       10 | avg:    0.042 ms | max:    0.113 ms | max at: 9804.958698 s
        events/2:53           |      0.676 ms |       10 | avg:    0.037 ms | max:    0.102 ms | max at: 9814.751605 s
        perf:11155            |      2.109 ms |        1 | avg:    0.068 ms | max:    0.068 ms | max at: 9814.867918 s
      
      TASK:进程名和pid。
      Runtime:实际的运行时间。
      Switches:进程切换的次数。
      Average delay:平均的调度延迟。
      Maximum delay:最大的调度延迟。
      Maximum delay at:最大调度延迟发生的时刻。
      

      例8

      #  perf probe --line schedule    #前面有行号的可以探测,没有行号的就不行了
      
      #  perf report latency --sort max    #在schedule函数的12处增加一个探测点
      

      perf火焰图大量unknown的问题

      使用 perf 进行性能分析时如何获取准确的调用栈

      工具之术

      • Debug
      • Linux
      • x86

      perf 是 Linux 下重要的性能分析工具,perf 可以通过采样获取很多性能指标,其中最常用的是获取 CPU Cycles,即程序各部分代码运行所需的时间,进而确定性能瓶颈在哪。不过在实际使用过程中发现,简单的使用perf record -g 获取到的调用栈是有问题的,存在大量 [Unknown] 函数,从 perf report 的结果来看这些部分对应地址大部分都是非法地址,且生成的火焰图中存在很多明显与代码矛盾的调用关系。

      最初怀疑是优化级别的问题,然而尝试使用 Og 或 O0 优化依然存在此问题,仔细阅读 perf record 的手册后发现,perf 同时支持 3 种栈回溯方式:fp, dwarf, lbr,可以通过 --call-graph 参数指定,而 -g 就相当于 --call-graph fp.

      栈回溯方式

      fp 就是 Frame Pointer,即 x86 中的 EBP 寄存器,fp 指向当前栈帧栈底地址,此地址保存着上一栈帧的 EBP 值,具体可参考此文章的介绍,根据 fp 就可以逐级回溯调用栈。然而这一特性是会被优化掉的,而且这还是 GCC 的默认行为,在不手动指定 -fno-omit-frame-pointer 时默认都会进行此优化,此时 EBP 被当作一般的通用寄存器使用,以此为依据进行栈回溯显然是错误的。不过尝试指定 -fno-omit-frame-pointer 后依然没法获取到正确的调用栈,根据 GCC 手册的说明,指定了此选项后也并不保证所有函数调用都会使用 fp…… 看来只有放弃使用 fp 进行回溯了。

      dwarf 是一种调试文件格式,GCC 编译时附加的 -g 参数生成的就是 dwarf 格式的调试信息,其中包括了栈回溯所需的全部信息,使用 libunwind 即可展开这些信息。dwarf 的进一步介绍可参考 “关于DWARF”,值得一提的是,GDB 进行栈回溯时使用的正是 dwarf 调试信息。实际测试表明使用 dwarf 可以很好的获取到准确的调用栈。

      最后 perf 还支持通过 lbr 获取调用栈,lbr 即 Last Branch Records,是较新的 Intel CPU 中提供的一组硬件寄存器,其作用是记录之前若干次分支跳转的地址,主要目的就是用来支持 perf 这类性能分析工具,其详细说明可参考 “An introduction to last branch records” & “Advanced usage of last branch records”。此方法是性能与准确性最高的手段,然而它存在一个很大的局限性,由于硬件 Ring Buffer 寄存器的大小是有限的,lbr 能记录的栈深度也是有限的,具体值取决于特定 CPU 实现,一般就是 32 层,若超过此限制会得到错误的调用栈。

      测试

      实际测试下以上 3 种栈回溯方式得到的结果,测试程序是一个调用深度为 50 的简单程序,从 f0() 依次调用至 f50()。

      **--call-graph fp**:

      (图:略,请到原文查看)

      **--call-graph lbr**:

      (图:略,请到原文查看)

      **--call-graph dwarf**:

      (图:略,请到原文查看)

      可以看到,的确只有 dwarf 获取到了正确的调用栈。

      总结

        优点 缺点
      fp None 1. 默认 fp 被优化掉了根本不可用。
      lbr 1. 高效准确 1. 需要较新的 Intel CPU 才有此功能;2. 能记录的调用栈深度有限。
      dwarf 1. 准确 1. 开销相对较大;2. 需要编译时附加了调试信息。

      perf 的工作原理

      基本原理是:

            每隔一个固定时间,CPU上产生一个中断,看当前是哪个进程、哪个函数,然后给对应的进程和函数加一个统计值,这样就知道CPU有多少时间在某个进程或某个函数上了。具体原作原理就是直接通过系统调用syscall/ioctl或者监听SW的event来看性能。

      详细见本章节内容:

      2.1 背景知识
      2.1.1 tracepoints
      tracepoints是散落在内核源码中的一些hook,它们可以在特定的代码被执行到时触发,这一特定可以被各种trace/debug工具所使用。

      perf将tracepoint产生的时间记录下来,生成报告,通过分析这些报告,可以了解程序运行期间内核的各种细节,对性能症状做出准确的诊断。

      2.1.2 硬件特性之cache
      内存读写是很快的,但是还是无法和处理器指令执行速度相比。为了从内存中读取指令和数据,处理器需要等待,用处理器时间来衡量,这种等待非常漫长。cache是一种SRAM,读写速度非常快,能和处理器相匹配。因此将常用的数据保存在cache中,处理器便无需等待,从而提高性能。cache的尺寸一般都很小,充分利用cache是软件调优非常重要部分

      2.2 调优方向
      Hardware Event由PMU部件产生,在特定的条件下探测性能事件是否发生以及发生的次数

      Software Event是内核产生的事件,分布在各个功能模块中,统计和操作系统相关性能事件。比如进程切换,ticks等。

      Tracepoint Event是内核中静态tracepoint所触发的事件,这些tracepoint用来判断程序运行期间内核的行为细节。比如slab分配器的分配次数等。

      3、Perf检测原理
      perf是利用PMU、tracepoint和内核中的计数器来进行性能统计

      3.1 PMU

      【性能】perf + 火焰图分析软件性能瓶颈
      PerformanceMonitor Unit,性能监视单元,其为CPU提供的一个单元,属于硬件的范畴。通过访问相关的寄存器能读取到CPU的一些性能数据,目前大部分CPU都会提供相应的PMU。其包括各种core, offcore和uncore事件

      Perf可以对程序进行函数级别的采样,从而了解程序的性能瓶颈在哪里。其基本原理是:每隔一个固定时间,就是CPU上产生一个中断,看当前是哪个进程、哪个函数,然后给对应的进程和函数加一个统计值,这样就知道CPU有多少时间在某个进程或某个函数上了。具体原作原理就是直接通过系统调用syscall/ioctl或者监听SW的event来看性能。

      perf是一个面向事件(event-oriented)的性能检测工具,内置于Linux内核,又称 perf_events

      event 可能的来源:

      【性能】perf + 火焰图分析软件性能瓶颈

      perf 工具将 event 分为:

      software events,hardware events,hardware cache events,tracepoint events


      software events
      使用内核的计数器 kernel counters,记录系统级事件,例如上下文切换,page fault等

      hardware events
      使用CPU的 Performance Monitoring Unit (PMU),记录微体系结构(micro-architecture)事件,例如cycle数,指令执行数 instructions retired,L1 cache misses等
      PMU是一种寄存器,用于记录指定事件发生的次数(perf stat -e 多个事件用逗号隔开)。使用PMU计数时,会设定 Sample After Value (SAV)。当PMU的值超过SAV,将触发一个硬件中断,中断处理程序可以收集CPU的IP,调用堆栈,PID等信息,并认为这SAV次事件都是由于当前指令造成的。


      hardware events 记录的误差可能来自于:

      超线程共享PMU: 开启超线程后,一个物理核心被虚拟化为两个逻辑核心,但依然共用同一个PMU
      事件滑行(Hardware Event Skid): 硬件延迟或指令流重排导致记录的IP并没指向真正发生事件的指令
      多路复用:如果记录的事件种类超过了PMU的数量,会对PMU进行多路(时分)复用
      中断屏蔽: 用于记录指令的这个中断可能会被其它中断屏蔽掉
      详细参考: Understanding How General Exploration Works in Intel® VTune™ Amplifier

      hardware cache events
      一类特别的 hardware events:有 L1 (d/i)cache, LLC(Last Level Cache), (d/i)TLB, branch 事件

      tracepoint events
      内核提供的 ftrace 系统调度追踪器

      最常用到的命令:
      perf stat: obtain event counts
      perf record: record events for later reporting
      perf report: break down events by process, function, etc.
      perf annotate: annotate assembly or source code with event counts
      perf top: see live event count
      perf bench: run different kernel microbenchmarks

      版权声明:本文内容来自第三方投稿或授权转载,原文地址:https://blog.csdn.net/bandaoyu/article/details/108765693,作者:bandaoyu,版权归原作者所有。本网站转在其作品的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如因作品内容、版权等问题需要同本网站联系,请发邮件至ctyunbbs@chinatelecom.cn沟通。

      上一篇:【协程】协程有什么用?什么是协程?

      下一篇:LeetCode专题-Python实现之第20题:Valid Parentheses

      相关文章

      2025-04-22 09:44:09

      【Java】this关键字的使用

      【Java】this关键字的使用

      2025-04-22 09:44:09
      对象 , 属性 , 当前 , 构造方法 , 调用
      2025-04-22 09:40:08

      通过java调用shell脚本实现服务的重启

      通过java调用shell脚本实现服务的重启

      2025-04-22 09:40:08
      shell , 服务 , 脚本 , 调用
      2025-04-22 09:40:08

      【Linux】Java进程CPU 使用率过高问题排查

      【Linux】Java进程CPU 使用率过高问题排查

      2025-04-22 09:40:08
      CPU , 打印 , 进程
      2025-04-18 08:02:09

      CUDA从入门到精通(二)——NVCC编译器介绍

      nvcc(NVIDIA CUDA Compiler)是 NVIDIA CUDA 编程工具链中的编译器驱动程序。它负责将基于 CUDA C/C++ 编写的代码编译成能够在 NVIDIA GPU 上执行的程序。

      2025-04-18 08:02:09
      CPU , CUDA , GPU , 代码 , 编译
      2025-04-18 08:01:53

      Java中关于多态的问题

      Java中关于多态的问题

      2025-04-18 08:01:53
      多态 , 子类 , 对象 , 方法 , 调用
      2025-04-18 08:01:53

      Java中关于自定义异常类的一些问题

      Java中定义了大量的异常类,虽然这些异常类可以描述编程时出现的大部分异常情况,但是在程序开发中,有时还需要描述程序中特有的异常情况。为了解决这种情况,Java允许用户自定义异类。

      2025-04-18 08:01:53
      catch , throws , 异常 , 抛出 , 方法 , 自定义 , 调用
      2025-04-15 09:20:33

      初学Java,在构造器中调用另一个构造器(十)

      初学Java,在构造器中调用另一个构造器(十)

      2025-04-15 09:20:33
      base , Java , super , 构造 , 父类 , 调用
      2025-04-15 09:19:05

      文心一言 VS 讯飞星火 VS chatgpt (282)-- 算法导论20.4 3题

      在并查集(Union-Find)算法中,CONNECTED-COMPONENTS 通常指的是一个过程,它遍历图中的所有边,并对每个边调用 UNION 操作以合并两个顶点所属的集合,直到没有边需要处理为止。这个过程中,FIND-SET 操作通常在 UNION 操作之前被调用,以确定两个顶点当前所属的集合。

      2025-04-15 09:19:05
      SET , UNION , 调用 , 连通
      2025-04-15 09:18:30

      五种 IO 模型介绍 与 fcntl实现 非阻塞 IO

      五种 IO 模型介绍 与 fcntl实现 非阻塞 IO

      2025-04-15 09:18:30
      IO , 异步 , 描述符 , 调用 , 阻塞
      2025-04-14 09:28:32

      【C语言】指针初阶2.0

      【C语言】指针初阶2.0

      2025-04-14 09:28:32
      指针 , 数组 , 调用
      查看更多
      推荐标签

      作者介绍

      天翼云小翼
      天翼云用户

      文章

      32777

      阅读量

      4816275

      查看更多

      最新文章

      【Java】this关键字的使用

      2025-04-22 09:44:09

      【Linux】Java进程CPU 使用率过高问题排查

      2025-04-22 09:40:08

      CUDA从入门到精通(二)——NVCC编译器介绍

      2025-04-18 08:02:09

      Java中关于多态的问题

      2025-04-18 08:01:53

      Java中关于自定义异常类的一些问题

      2025-04-18 08:01:53

      初学Java,在构造器中调用另一个构造器(十)

      2025-04-15 09:20:33

      查看更多

      热门文章

      Python 函数调用父类详解

      2023-04-23 09:44:31

      Java学习之方法调用过程图解(理解)

      2023-04-06 06:35:24

      qt调用外部程序(exe)

      2023-06-27 10:00:24

      多线程基础

      2024-09-25 10:14:34

      Linux内核之进程3:进程调度

      2024-04-16 08:57:13

      线程简介

      2024-04-16 02:57:57

      查看更多

      热门标签

      java Java python 编程开发 开发语言 代码 算法 线程 html Python 数组 C++ javascript c++ 元素
      查看更多

      相关产品

      弹性云主机

      随时自助获取、弹性伸缩的云服务器资源

      天翼云电脑(公众版)

      便捷、安全、高效的云电脑服务

      对象存储

      高品质、低成本的云上存储服务

      云硬盘

      为云上计算资源提供持久性块存储

      查看更多

      随机文章

      【JVM调优】内存溢出+CPU占用过高:问题排查+解决方案+复盘

      黑马程序员Java教程学习笔记(二)

      软件架构设计师需要记住的内容(软件架构)

      【C++】什么是多态?虚函数的底层实现原理|多重继承|菱形继承

      如何在Windows服务做性能测试(CPU、磁盘、内存)

      【调试】strace命令|跟踪进程系统调用和所接收的信号|查找依赖库失败|linux

      • 7*24小时售后
      • 无忧退款
      • 免费备案
      • 专家服务
      售前咨询热线
      400-810-9889转1
      关注天翼云
      • 权益商城
      • 天翼云APP
      • 天翼云微信公众号
      服务与支持
      • 备案中心
      • 售前咨询
      • 智能客服
      • 自助服务
      • 工单管理
      • 客户公告
      • 涉诈举报
      账户管理
      • 管理中心
      • 订单管理
      • 余额管理
      • 发票管理
      • 充值汇款
      • 续费管理
      快速入口
      • 权益商城
      • 文档中心
      • 最新活动
      • 免费试用
      • 信任中心
      • 天翼云学堂
      云网生态
      • 甄选商城
      • 渠道合作
      • 云市场合作
      了解天翼云
      • 关于天翼云
      • 天翼云APP
      • 服务案例
      • 新闻资讯
      • 联系我们
      热门产品
      • 云电脑
      • 弹性云主机
      • 云电脑政企版
      • 天翼云手机
      • 云数据库
      • 对象存储
      • 云硬盘
      • Web应用防火墙
      • 服务器安全卫士
      • CDN加速
      热门推荐
      • 云服务备份
      • 边缘安全加速平台
      • 全站加速
      • 安全加速
      • 云服务器
      • 云主机
      • 智能边缘云
      • 应用编排服务
      • 微服务引擎
      • 共享流量包
      更多推荐
      • web应用防火墙
      • 密钥管理
      • 等保咨询
      • 安全专区
      • 应用运维管理
      • 云日志服务
      • 文档数据库服务
      • 云搜索服务
      • 数据湖探索
      • 数据仓库服务
      友情链接
      • 中国电信集团
      • 189邮箱
      • 天翼企业云盘
      • 天翼云盘
      ©2025 天翼云科技有限公司版权所有 增值电信业务经营许可证A2.B1.B2-20090001
      公司地址:北京市东城区青龙胡同甲1号、3号2幢2层205-32室
      • 用户协议
      • 隐私政策
      • 个人信息保护
      • 法律声明
      备案 京公网安备11010802043424号 京ICP备 2021034386号