性能分析小案例系列,可以通过下面链接查看哦

https://www.cnblogs.com/poloyy/category/1814570.html

前言

  • 前面两个案例讲的都是上下文切换导致的 CPU 使用率升高
  • 这一篇就来讲讲等待 I/O 导致的 CPU 使用率升高的案例

进程状态

详解进程状态

https://www.cnblogs.com/poloyy/p/13413770.html

不可中断状态

  • 当 iowait 升高时,进程很可能因为得不到硬件的响应,而长时间处于不可中断状态
  • 不可中断也是为了保护进程数据和硬件状态一致,并且正常情况下,不可中断状态在很短时间内就会结束
  • 所以,短时的不可中断进程,一般可以忽略
  • 但如果系统或硬件发生了故障,进程可能会在不可中断状态保持很久,甚至导致系统中出现大量不可中断进程。这时,就得注意下,系统是不是出现了 I/O 等性能问题

僵尸进程

多进程引用很容易碰到的问题

正常情况

  • 一个进程创建了子进程后,它应该通过系统调用 wait() 或 waitpid() 等待子进程结束,回收子进程的资源
  • 而子进程在结束时,会向它的父进程发送 SIGCHLD 信号
  • 所以,父进程还可以注册 SIGCHLD 信号的处理函数,异步回收资源

异常情况

  • 如果父进程没有回收资源,或是子进程执行太快,父进程还没来得及处理子进程状态,子进程就已经提前退出,那这时的子进程就会变成僵尸进程
  • 形象比喻:父亲应该一直对儿子负责, 善始善终,如果不作为或者跟不上,都会导致“问题少年”的出现

重点

  • 僵尸进程持续的时间都比较短,在父进程回收它的资源后就会消亡,或者在父进程退出后,由 init 进程回收后也会消亡
  • 一旦父进程没有处理子进程的终止,还一直保持运行状态,那么子进程就会一直处于僵尸状态
  • 大量的僵尸进程会用尽 PID 进程号,导致新进程不能创建

大量不可中断状态和僵尸状态进程的案例

系统配置

  • Ubuntu 18.04, 2 CPU,2GB 内存
  • 前置条件:已运行案例应用

通过 ps 命令查看案例进程

ps aux | grep /app

结果分析

  • 多个 app 进程已启动
  • 状态有 Ss+、D+、R+
  • 小s:表示这个进程是一个会话的领导进程
  • +:表示前台进程组

什么是会话和进程组

  • 它们是用来管理一组相互关联的进程
  • 进程组:比如每个子进程都是父进程所在组的成员
  • 会话:共享同一个控制终端的一个或多个进程组

会话和进程组的场景类比

  • 通过 SSH 登录服务器,就会打开一个控制终端(TTY),这个控制终端就对应 一个会话
  • 而在终端中运行的命令以及它们的子进程,就构成了一个个的进程组
  • 后台运行的命令,构成后台进程组
  • 前台运行的命令,构成前台进程组

通过 top 查看系统状况

结果分析

  • 平均负载,过去 1min、5min、15min 的平均负载依次减少,说明平均负载正在升高
  • 而 1min 内的平均负载已经达到系统 CPU 个数,说明系统很可能存在性能瓶颈
  • 115 zombie 说明僵尸进程比较多,而且在不停增加,有子进程在退出时没被清理
  • 用户 CPU 和系统 CPU 都不高,但 iowait 分别是 60.5% 和 94.6%,好像有点儿不正常,导致系统的平均负载升高
  • 有两个处于 D 状态的 app 进程,可能在等待 I/O

查看系统的僵尸进程

ps -e -o stat,ppid,pid,cmd | egrep '^[Zz]' 

或

ps -ef | grep "defunct"

一堆 app 僵尸进程

iowait 分析

一提到 iowait 升高,首先会想要查询系统的 I/O 情况

运行 dstat 命令,观察 CPU 和 I/O 的使用情况

dstat  

  • 当 iowait 升高(wai)时,磁盘的请求(read)都会很大(M)
  • 这说明 iowait 的升高跟磁盘的读请求有关,很可能就是读磁盘导致的

找到读磁盘的进程

  • 通过 top 找到 D 状态的两个 app 进程
  • 不可中断状态代表进程在跟硬件进行交互,很可能就是读磁盘

两个 app 进程的 PID 分别是12407、12406

通过 pidstat 查看 app 进程的 I/O 情况

pidstat -d -p   
  • -d 展示 I/O 统计数据
  • -p 指定进程号
  • 间隔 1 秒输出 5 组数据

  • kB_rd 表示每秒的 KB 数, kB_wr 表示每秒的 KB 数,iodelay 表示 I/O 的延迟(单位是时钟周期)
  • 它们都是 0,那就表示此时没有任何的读写,说明问题不 是 12407 进程导致的,也并不是12406 进程导致的

通过 pidstat 查看系统的 I/O 情况

pidstat -d  

  • 能看到其实的确是 app 进程在读,只不过每过几秒都会有新的 app 进程在读【pid 在不断变化】
  • 可以确认,是 app 进程的问题

通过 ps 命令查看一直变化的 app 进程状态

前面讲到读磁盘的 app 进程 PID 一直在变化,那么就来看看已经没在读磁盘的进程的进程状态是怎么样的

ps aux | grep 

  • 这进程已经是 Z 状态,就是僵尸进程
  • 僵尸进程都是已经退出的进程, 所以就没法儿继续分析它的系统调用
  • 关于僵尸进程的处理方法,我们一会儿再说,现在还是继续分析 iowait 的问题

通过 perf 录制性能事件

  • 系统 iowait 的问题还在继续,但是 top、pidstat 这类工具已经不能给出更多的信息了
  • 此时可以通过 perf 动态跟踪性能事件
perf record -g

15s 后 ctrl+c 终止录制

查看报告,分析报告

perf report

  • app 的确在通过系统调用 sys_read() 读取数据
  • 并且从 new_sync_read 和 blkdev_direct_IO 能看出,进程正在对磁盘进行直接读,也就是绕过了系统缓存,每个读请求都会从磁盘直接读,这就可以解释观察到的 iowait 升高了

修复源码之后,通过 top 命令验证

  • iowait 已经非常低了,只有 0.3%
  • 说明修改源码已经成功修复了 iowait 高的问题
  • 不过,仔细观察僵尸进程的数量,会发现,僵尸进程还在不断的增长中

处理和分析僵尸进程

  • 僵尸进程是因为父进程没有回收子进程的资源而出现的
  • 解决僵尸进程需要先找出父进程,然后在父进程里解决

通过 pstree 找到某个 app 进程的父进程

pstree -aps 

51780 进程的父进程是 51688,也就是 app 应用

通过 ps 查看所有僵尸进程的父进程

ps -e -o stat,ppid,pid,cmd | egrep '^[Zz]'

所有僵尸进程的父进程都是 51688,从而确认 51688 就是僵尸进程的父进程

查看 app 应用程序的代码

查看 app 应用程序的代码,看看子进程结束的处理是否正确

  1. 有没有调用 wait() 或 waitpid()
  2. 或有没有注册 SIGCHLD 信号的处理函数

把 wait() 放到了 for 死循环的外面,也就是说, wait()  函数实际上并没被调用到,把它挪到 for 循环的里面就可以了

改完源码,通过 top 验证一下

僵尸进程(Z 状态)没有了, iowait 也是 0,问题终于全部解决了

总结

  • 这个案例是因为磁盘 I/O 导致了 iowait 升高
  • 不过,iowait 高并不一定代表 I/O 有性能瓶颈
  • 当系统中只有 I/O 类型的进程在运行时,iowait 也会很高,但实际上,磁盘的读写远没有达到性能瓶颈的程度

分析整体思路

  1. 通过 top 查看系统资源情况
  2. 发现平均负载逐渐升高,iowait(wa)比较高,但用户态和内核态 CPU 使用率并不算高
  3. 查看是否有 CPU 使用率偏高的进程,发现有 D 状态的进程,可能是在等待 I/O 中
  4. 过一阵子会变成 Z 状态进程,且 CPU 使用率上升,然后会看到 zombie 进程数逐渐增加
  5. 可以得到两个结论:僵尸进程过多,应该是父进程没有清理已经结束的子进程的资源;iowait 的上升导系统平均负载上升
  6. 因为是 iowait 较高,可以通过 dstat 查看系统的 I/O 情况,会发现每次 iowait 升高,读磁盘请求都会很大
  7. 通过 pidstat -d 查看 D 状态进程的 I/O 情况,但发现并没有有效信息
  8. 通过 pidstat -d 直接查看系统的 I/O 情况,可以发现不断有新进程在进行读磁盘操作
  9. 通过 ps 命令查看刚刚 D 状态进程当前的进程状态,发现已经变成僵尸进程
  10. 通过 perf record 录制性能事件,然后通过 perf report 查看性能报告,可以发现 app 进程都是直接读磁盘,而不经过系统缓存
  11. 通过 pstree 找到 Z 状态进程的父进程
  12. 通过 ps 命令确认所有僵尸进程的父进程
  13. 找到父进程源代码,检查 wait() / waitpid() 的是否会成功调用,或是 SIGCHLD 信号处理函数的注册就行了
  14. 修改完全部源码后,重新运行应用,通过 top 验证是否还有 iowait 过高和出现 zombie 进程的情况

性能分析(4)- iowait 使用率过高案例的更多相关文章

  1. 性能分析(3)- 短时进程导致用户 CPU 使用率过高案例

    性能分析小案例系列,可以通过下面链接查看哦 https://www.cnblogs.com/poloyy/category/1814570.html 系统架构背景 VM1:用作 Web 服务器,来模拟 ...

  2. 性能分析(2)- 应用程序 CPU 使用率过高案例

    性能分析小案例系列,可以通过下面链接查看哦 https://www.cnblogs.com/poloyy/category/1814570.html 系统架构背景 其中一台用作 Web 服务器,来模拟 ...

  3. Linux 性能分析调优 (四)——案例篇:系统中出现大量不可中断进程和僵尸进程怎么办

    之前讲到 CPU 使用率的类型.除了上一节提到的用户 CPU 之外,它还包括系统 CPU(比如上下文切换).等待 I/O 的 CPU(比如等待磁盘的响应)以及中断 CPU(包括软中断和硬中断)等. 在 ...

  4. 性能分析 | Java服务器内存过高&CPU过高问题排查

    一.内存过高 1.内存过高一般有两种情况:内存溢出和内存泄漏 (1)内存溢出:程序分配的内存超出物理机的内存大小,导致无法继续分配内存,出现OOM报错 (2)内存泄漏:不再使用的对象一直占据着内存不释 ...

  5. 性能分析 | Java进程CPU占用高导致的网页请求超时的故障排查

    一.发现问题的系统检查: 一个管理平台门户网页进统计页面提示请求超时,随进服务器操作系统检查load average超过4负载很大,PID为7163的进程占用到了800%多. 二.定位故障 根据这种故 ...

  6. Hi,腾讯WeTest联合Unity官方打造的性能分析工具UPA,今日全新发布!

    早在2016年ChinaJoy开始,WeTest曾受邀出席过Unity中国的线下性能场的活动,介绍我们的自动化框架和王者荣耀的故事.当时的活动很成功,期间我们收到了不少Unity开发者的好评,也为我们 ...

  7. 性能分析(5)- 软中断导致 CPU 使用率过高的案例

    性能分析小案例系列,可以通过下面链接查看哦 https://www.cnblogs.com/poloyy/category/1814570.html 前言 软中断基本原理,可参考这篇博客:https: ...

  8. 性能测试学习第十天-----性能案例分析之CPU消耗过高&响应时间较长

    一.现象  /pinter/case/cpu?type=1   使用google的gjson.tojson性能较差    type=2 使用性能好的阿里巴巴的fastjson库 压测过程中,发现应用服 ...

  9. 06 案例篇:系统的 CPU 使用率很高,但为啥却找不到高 CPU 的应用?

    上一节我讲了 CPU 使用率是什么,并通过一个案例教你使用 top.vmstat.pidstat 等工具,排查高 CPU 使用率的进程,然后再使用 perf top 工具,定位应用内部函数的问题.不过 ...

随机推荐

  1. redis必知会

    Redis 是单进程单线程的? Redis 是单进程单线程的,redis 利用队列技术将并发访问变为串行访问,消 除了传统数据库串行控制的开销. Redis 的持久化机制是什么?各自的优缺点? Red ...

  2. OSCP Learning Notes - Scanning(2)

    Scanning with Metasploite: 1. Start the Metasploite using msfconsole 2. search modules 3.Choose one ...

  3. onehot编码检测

    ‘’16bits位宽寄存器,用五(六也行)级逻辑判断其中有15个0和1个1‘’,这么道题目,面试无数,几乎没有人能答出来,连给我衍生‘’14个0和2个1‘’的机会都没有. 今天的问题来源于知乎,某大牛 ...

  4. 微信小程序反编译~2020年

    目录 摘要 介绍 安装反编译脚本 使用 获取wxapkg文件 反编译 结论 参考资料 摘要 安装wxappUnpacker小程序反编译工具并使用(2020.03) 关键词: 微信小程序反编译 wxss ...

  5. DNS反向查询

    DNS反向查询是什么 DNS反向查询大概的一个定义就是: 从 IP 地址获取 PTR 记录.也就是说,通过使用一些网络工具可以将 IP 地址转换为主机名. 实际上,PRT 代表 POINTER,在 D ...

  6. 题解 洛谷 P5385 【[Cnoi2019]须臾幻境】

    首先我们知道 \(n\) 个点的树有 \(n-1\) 条边,因此对于森林来说,其点数减边数即为树的个数.那么对于普通的图,求出其任意一个生成树森林,森林中树的个数即为原图中连通块的个数,也就是点数减边 ...

  7. Linux系统中(CentOS 7)的用户和权限管理

    目录 用户和组 用户信息文件 用户密码信息 相关命令 用户管理 组管理 密码管理 权限管理 文件的详细信息 文件权限 相关命令 用户和组 用户信息文件 /etc/passwd (1 2 3 4 5 6 ...

  8. 基于Scrapy的B站爬虫

    基于Scrapy的B站爬虫 最近又被叫去做爬虫了,不得不拾起两年前搞的东西. 说起来那时也是突发奇想,想到做一个B站的爬虫,然后用的都是最基本的Python的各种库. 不过确实,实现起来还是有点麻烦的 ...

  9. 对于Javaweb初学者的一些坑。#Javaweb

    1.在配置好Tomcat之后 ,编译阶段发现报错 这种对于我个人来说一般有两种情况: ①在编写代码时(比如servlet)发现爆红,一般是maven的依赖没有导入,这个时候在xml文件中导入需要的包的 ...

  10. Linux系统安装Samba共享服务器详解及安装配置

    一.简介 Samba服务程序是一款基于SMB协议并由服务端和客户端组成的开源文件共享软件,实现了Linux和windows系统间的文件共享.SMB(Server Messages Block,信息服务 ...