一、实验环境

二、实验案例分析

安装完成后,我们先在第一个终端,执行下面的命令运行案例,也就是一个最基本的 Nginx 应用:

运行 Nginx 服务并对外开放 80 端口

# docker run -itd --name=nginx -p 80:80  nginx

然后,在第二个终端,使用 curl 访问 Nginx 监听的端口,确认 Nginx 正常启动。

假设 192.168.0.30 是 Nginx 所在虚拟机的 IP 地址,运行 curl 命令后,你应该会看到下面这个输出界面:

#  curl http://192.168.0.30/

接着,还是在第二个终端中,运行 hping3 命令,模拟 Nginx 的客户端请求:

#  hping3 -S -p 80 -i u10 192.168.0.30

现在,我们再回到第一个终端,你应该就会发现异常——系统的响应明显变慢了。

我们不妨执行 top,观察一下系统和进程的 CPU 使用情况:

从 top 的输出中,你可以看到,两个 CPU 的软中断使用率都超过了 30%;而 CPU 使用率最高的进程,正好是软中断内核线程 ksoftirqd/0 和 ksoftirqd/1。

虽然,我们已经知道了 ksoftirqd 的基本功能,可以猜测是因为大量网络收发,引起了 CPU 使用率升高;但它到底在执行什么逻辑,我们却并不知道。

对于普通进程,我们要观察其行为有很多方法,比如 strace、pstack、lsof 等等。但这些工具并不适合内核线程,比如,如果你用 pstack ,或者通过 /proc/pid/stack 查看 ksoftirqd/0(进程号为 9)的调用栈时,分别可以得到以下输出:

那还有没有其他方法,来观察内核线程 ksoftirqd 的行为呢?

既然是内核线程,自然应该用到内核中提供的机制。回顾一下我们之前用过的 CPU 性能工具,我想你肯定还记得 perf ,这个内核自带的性能剖析工具。

perf 可以对指定的进程或者事件进行采样,并且还可以用调用栈的形式,输出整个调用链上的汇总信息。

我们不妨就用 perf ,来试着分析一下进程号为 9 的 ksoftirqd。

#  perf record -a -g -p 9 -- sleep 30

#################################################################

# man perf

# man 1 perf-record

perf-record - Run a command and record its profile into perf.data

-a, --all-cpus        System-wide collection from all CPUs (default if no target is specified).

-g                       Enables call-graph (stack chain/backtrace) recording.

-p, --pid=      Record events on existing process ID (comma separated list).

##################################################################

稍等一会儿,在上述命令结束后,继续执行 perf report命令,你就可以得到 perf 的汇总报告。

按上下方向键以及回车键,展开比例最高的 ksoftirqd 后,你就可以得到下面这个调用关系链图:

从这个图中,你可以清楚看到 ksoftirqd 执行最多的调用过程。

虽然你可能不太熟悉内核源码,但通过这些函数,我们可以大致看出它的调用栈过程。

我们的猜测对不对呢?

实际上,我们案例最开始用 Docker 启动了容器,而 Docker 会自动为容器创建虚拟网卡、桥接到 docker0 网桥并配置 NAT 规则。

这一过程,如下图所示:

当然了,前面 perf report 界面的调用链还可以继续展开。

不幸的是我的屏幕不够大,如果展开更多的层级,最后几个层级会超出屏幕范围。

这样,即使我们能看到大部分的调用过程,却也不能说明后面层级就没问题。

那么,有没有更好的方法,来查看整个调用栈的信息呢?

火焰图

针对 perf 汇总数据的展示问题,Brendan Gragg 发明了火焰图,通过矢量图的形式,更直观展示汇总结果。

下图就是一个针对 MySQL 的火焰图示例。

图片来自 Brendan Gregg 博客

这张图看起来像是跳动的火焰,因此也就被称为火焰图。

要理解火焰图,我们最重要的是区分清楚横轴和纵轴的含义:

上面 MySQL 火焰图的示例,就表示了 CPU 的繁忙情况,这种火焰图也被称为 on-CPU 火焰图。

如果我们根据性能分析的目标来划分,火焰图可以分为下面这几种:

了解了火焰图的含义和查看方法后,接下来,我们再回到案例,运用火焰图来观察刚才 perf record 得到的记录。

火焰图分析

首先,我们需要生成火焰图。我们先下载几个能从 perf record 记录生成火焰图的工具,这些工具都放在 https://github.com/brendangregg/FlameGraph 上面。

你可以执行下面的命令来下载:

#  git clone https://github.com/brendangregg/FlameGraph

#  cd FlameGraph

安装好工具后,要生成火焰图,其实主要需要三个步骤:

执行 perf script ,将 perf record 的记录转换成可读的采样记录;

执行 stackcollapse-perf.pl 脚本,合并调用栈信息;

执行 flamegraph.pl 脚本,生成火焰图。

不过,在 Linux 中,我们可以使用管道,来简化这三个步骤的执行过程。

假设刚才用 perf record 生成的文件路径为 /root/perf.data,执行下面的命令,你就可以直接生成火焰图:

# perf script -i  /root/perf.data | ./stackcollapse-perf.pl --all | ./flamegraph.pl > ksoftirqd.svg

执行成功后,使用浏览器打开 ksoftirqd.svg ,你就可以看到生成的火焰图了。

如下图所示:

根据刚刚讲过的火焰图原理,这个图应该从下往上看,沿着调用栈中最宽的函数来分析执行次数最多的函数。

这儿看到的结果,其实跟刚才的 perf report 类似,但直观了很多,中间这一团火,很明显就是最需要我们关注的地方。

我们顺着调用栈由下往上看(顺着图中蓝色箭头),就可以得到跟刚才 perf report 中一样的结果:

不过最后,到了 ip_forward 这里,已经看不清函数名称了。

所以我们需要点击 ip_forward,展开最上面这一块调用栈:

这样,就可以进一步看到 ip_forward 后的行为,也就是把网络包发送出去。根据这个调用过程,再结合我们前面学习的网络收发和 TCP/IP 协议栈原理,这个流程中的网络接收、网桥以及 netfilter 调用等,都是导致软中断 CPU 升高的重要因素,也就是影响网络性能的潜在瓶颈。

不过,回想一下网络收发的流程,你可能会觉得它缺了好多步骤。

比如,这个堆栈中并没有 TCP 相关的调用,也没有连接跟踪 conntrack 相关的函数。实际上,这些流程都在其他更小的火焰中,你可以点击上图左上角的“Reset Zoom”,回到完整火焰图中,再去查看其他小火焰的堆栈。

所以,在理解这个调用栈时要注意,从任何一个点出发、纵向来看的整个调用栈,其实只是最顶端那一个函数的调用堆栈,而非完整的内核网络执行流程。

另外,整个火焰图不包含任何时间的因素,所以并不能看出横向各个函数的执行次序。

到这里,我们就找出了内核线程 ksoftirqd 执行最频繁的函数调用堆栈,而这个堆栈中的各层级函数,就是潜在的性能瓶颈来源。这样,后面想要进一步分析、优化时,也就有了根据。

当时,我们从软中断 CPU 使用率的角度入手,用网络抓包的方法找出了瓶颈来源,确认是测试机器发送的大量 SYN 包导致的。而通过今天的 perf 和火焰图方法,我们进一步找出了软中断内核线程的热点函数,其实也就找出了潜在的瓶颈和优化方向。

其实,如果遇到的是内核线程的资源使用异常,很多常用的进程级性能工具并不能帮上忙。这时,你就可以用内核自带的 perf 来观察它们的行为,找出热点函数,进一步定位性能瓶。当然,perf 产生的汇总报告并不够直观,所以我也推荐你用火焰图来协助排查。

实际上,火焰图方法同样适用于普通进程。比如,在分析 Nginx、MySQL 等各种应用场景的性能问题时,火焰图也能帮你更快定位热点函数,找出潜在性能问题。

CPU火焰图和内存火焰图,在生成数据时有什么不同?

CPU 火焰图和内存火焰图,最大的差别其实就是数据来源的不同,也就是函数堆栈不同,而火焰图的格式还是完全一样的。

火焰图的结构是一样的,只是函数堆栈不一样,内存火焰图侧重于内存管理函数的调用栈。

内存火焰图生成perf.data数据时,perf record加哪些选项?

要加上内存管理相关的事件(函数),比如 perf record -e syscalls:sys_enter_mmap -a -g -- sleep 60

三、参考

内核线程 CPU 利用率太高,我该怎么办?

https://time.geekbang.org/column/article/86330

SVG 图像入门教程

https://www.ruanyifeng.com/blog/2018/08/svg.html

SVG 简介

https://www.runoob.com/svg/svg-intro.html

如何读懂火焰图?

http://www.ruanyifeng.com/blog/2017/09/flame-graph.html

Linux程序性能分析和火焰图

https://www.cnblogs.com/pugang/p/10659301.html

Linux下用火焰图进行性能分析

https://blog.csdn.net/gatieme/article/details/78885908

火焰图介绍

https://book.aikaiyuan.com/linux/www.lijiaocn.com/linux/chapter1/04-flame-graphs.html

火焰图性能分析 perf

https://www.jevic.cn/2019/03/03/perf

perf + 火焰图分析程序性能

https://www.cnblogs.com/happyliu/p/6142929.html

使用 Perf 和火焰图分析 CPU 性能

http://senlinzhan.github.io/2018/03/18/perf

利用火焰图分析程序性能瓶颈

https://blog.angelmsger.com/%E5%88%A9%E7%94%A8%E7%81%AB%E7%84%B0%E5%9B%BE%E5%88%86%E6%9E%90%E7%A8%8B%E5%BA%8F%E6%80%A7%E8%83%BD%E7%93%B6%E9%A2%88

mysql火焰图_【性能】如何使用perf和火焰图分析系统性能?相关推荐

  1. hdc mfc 画扇形图_使用echarts绘制条形图和扇形图

    使用echarts绘制条形图和扇形图 简单举例说明下echarts如何绘制条形图和扇形图 代码示例 echarts绘制条形图和扇形图 var mychart1=echarts.init(documen ...

  2. c++思维导图_必看|用好思维导图,别神话思维导图

    不知不觉,时间已经划至5月中旬,20级的萌新们也从当初的"小白"不断进阶,化身老司机指日可待~ 相信从备考到现在,各位一定对"思维导图"这四个大字都听倦了!不管 ...

  3. html 甘特图_工具项目管理工具详解——甘特图

    作为项目的负责人,"时间管理"也是极为重要的一环.甘特图作为常用的项目管理工具之一,有助于把一个大型项目划分为几个小部分,并有条理地展示. 甘特图(Gantt chart)又称为横 ...

  4. python课程思维导图_零基础Python学习思维导图,记得收藏

    原标题:零基础Python学习思维导图,记得收藏 本文主要涵盖了 Python 编程的核心知识(暂不包括标准库及第三方库). 1.按顺序依次展示了以下内容的一系列思维导图:基础知识,数据类型(数字,字 ...

  5. python制作雷达图_如何利用Python matplotlib绘制雷达图

    本篇文章介绍使用matplotlib绘制雷达图. 雷达图也被称为网络图,蜘蛛图,星图,蜘蛛网图,是一个不规则的多边形.雷达图可以形象地展示相同事物的多维指标,雷达图几乎随处可见,应用场景非常多. 一. ...

  6. 关于主机的思维导图_送给孩子最好的思维导图课程

    思维导图寒假班来了 1关于思维导图思维导图是一种简单而有效的图形思维工具,主要元素包含图形.线条.关键字.颜色,配合下图,我们能理解思维导图利用了左脑和右脑的工作机理,能够充分调动大脑的分析推理和想象 ...

  7. java 性能 火焰图_性能调优工具-火焰图

    性能调优工具-火焰图 发布时间:2019-07-17 19:29, 浏览次数:402 前言 工具的进化一直是人类生产力进步的标志,合理使用工具能大大提高我们的工作效率,遇到问题时,合理使用工具更能加快 ...

  8. ali arthas 火焰图_性能优化之火焰图-2020-11-15

    背景 相信大家都有过jvm程序运行导致cpu100% ,或者飙高的场景.这个排查的方式有很多,比如 linux 自带的top pidstat mpstat等,还有一些开源工具arthas 等:这里我介 ...

  9. mysql客户端工具_性能优化-理解 MySQL 体系结构(MySQL分库分表)

    实例和数据库 我们通常所说的 MySQL 数据库服务器由一个实例(instance)以及一个数据库(database)组成.实例包括一组后台进程/线程和许多内存结构,用于管理数据库:数据库由一组磁盘文 ...

  10. mysql 递归查询 效率_性能优化实战-sql递归查询效率低下

    今天在做一个热门赛事列表查询的接口压测 http://192.168.10.98:8094/match/page?matchType=0&matchTime=0&matchStatus ...

最新文章

  1. 关于 top、left 结合 translate 实现居中的原理探讨
  2. 错误类型3错误:活动类{}不存在
  3. 什么是PyTorch?
  4. 各个平台看 docset 的工具
  5. java 任意数平均值_【编程题】通过键盘输入三个任意的数字,计算三个值的平均值,并输出结果。...
  6. 电脑上我的文档图标不见了怎么办
  7. Android测试提升效率批处理脚本
  8. Signal和Slot是同步的还是异步的
  9. 关于socket组播和ssdp(一)[修改1.2]
  10. 集算器协助MongoDB计算之交叉汇总
  11. 2018 Multi-University Training Contest 3: G. Interstellar Travel(凸包)
  12. spark-submit(spark版本2.3.2)
  13. c语言依次调用字符串中的元素,C语言经典题目(某校复试真题)
  14. 平时常见的音频文件格式有哪些呢?
  15. 【学习笔记】SAP资产模块
  16. svn拉取文件失败_TortoiseSVN常见的错误信息与解决方法
  17. 摄影教学 - 城市夜景
  18. 如何把多张图片合并成一个PDF?
  19. HDU 1300 Pearls(DP)
  20. Vue-router 使用编程式导航多次执行会报错NavigationDuplicated的解决方法

热门文章

  1. 图片工具picpick
  2. Linux通过Nodejs的IPP库实现自动定时打印
  3. OpenCV之findContours获取轮廓(Python版)
  4. 《禅与摩托车维修艺术》骑行路上的哲学思考
  5. 猴子搬香蕉(算法入门题目005)
  6. 《三体1:地球往事》读后感
  7. 【Latex】在图片标题中加入脚注
  8. 银河麒麟操作系统开发_银河初级开发者指南
  9. rpm mysql nokey_rpm包时遇到Header V3 DSA signature: NOKEY时解决办法
  10. cxf webservice接口