在上下班路上粗听了一遍倪朋飞老师的这个系列课程,让我弄清了很多原来似是而非的基本概念。所以,打算集中一段时间好好学习一下这个系列的课程,实际操作一下课程中的例子,并将心得体会记录在本文中。
课程连接: Linux性能优化实战
- 把观察到的性能问题跟系统原理关联起来,特别是把系统从应用程序、库函数、系统调用、再到内核和硬件等不同的层级贯穿起来。
在学习这个系列课程之前,我处理现场的性能问题时大都靠临时的搜索去完成,通过搜索引擎搜索到的东西零碎不成体系,有时后可以能够发挥作用,常常需要不断的去尝试不同的解决方案。解决问题后,有时也不能了解其中的原理。我想这就是没有贯通,没有从上到下打通问题从现象到本质,再到原理的路径,犹如习练武功,外功招式多,经脉未打通,内力有限。希望通过这个系列的课程,打通性能的任督二脉,内力更上一个台阶。
- 性能优化是个系统工程,总是牵一发而动全身。
众里寻她千百度。
-
性能优化是软件系统中最有挑战的工作之一,但是换个角度看,它也是最考验体现你综合能力的工作之一。
-
最好的学习方式一定是带着问题学习。
就是有目的的学习。
- 想要得到你就要学会付出,要付出还要坚持;如果你真的觉得很难,那你就放弃,如果你放弃了就不要抱怨。人生就是这样,世界是平衡的,每个人都是通过自己的努力,去决定自己生活的样子。
选择、努力。
- 建立起整体性能的全局观
理解原理,进行实践,也就是理论联系实际,知行合一。
- 性能指标是什么?
我们谈及性能,自然要明白性能的基本概念。性能指标就是观察性能的角度和衡量的标准。 文中从两个视角去观察性能: 一是应用的视角,即应用负载的指标,表示应用用了多少?;另一个是系统的视角,即系统资源的指标,表示还能用多少? 性能问题的本质是应用负载的增加导致系统资源达到瓶颈,这两者本来就是一对矛盾体,此消彼长。
- 解决性能问题的步骤:
六个步骤:
1.选择指标评估应用程序和系统的性能
2.为应用程序和系统设置性能目标
3.进行性能基准测试
4.性能分析定位瓶颈
5.优化系统和应用程序
6.性能监控和告警
- 学习的重点是什么?
“道”:理解最基本的几个系统知识原理;“器”:掌握必要的性能工具;“运用”:通过实际的场景演练,贯穿不同的组件
- 布伦丹·格雷格
大师,膜拜 网站Linux Performance
- 千万不要把性能工具当成学习的全部
工具是器,更重要的是掌握道
- 如何高效学习
技巧一:不要试图抓住所有的实现细节,抓重点,20-80原则;技巧二:边学边实践,知行合一;技巧三:勤思考、多反思、善总结,多问为什么
- 平均负载
可以通过man uptime来显示系统平均负载的定义(不能使用中文的language) 平均负载是在单位时间内,系统处于可运行状态和不可终中断状态的平均进程数
- 进程的状态
RDSTZIX
R
可运行状态 Running or runnable
表示正在运行或在运行队列上等待运行
D
不可中断的睡眠状态 Uninterruptible sleep
通常是一个系统关键的系统调用
S
可中断的睡眠状态 Interruptible sleep
表示正在等待事件
T
停止状态 Stopped
由于被挂起或被追踪
Z
僵尸状态 Defunct (zombie)
进程已经退出,但其父进程并没有回收进程
I
空闲状态 Idel
不可中断睡眠的内核进程。和D不同,不会造成平均负载升高
X
死亡 Dead
进程已经消亡。不会出现在top或ps中
- 平均负载为多少时合理
首先需要知道系统有几个CPU
grep 'model name' /proc/cpuinfo | wc -l
平均负载的三个值提供了系统负载趋势的数据。当平均负载高于 CPU 数量 70% 的时候,就应该分析排查负载高的问题
- 平均负载与 CPU 使用率
平均负载不仅包括正在使用 CPU 的进程,还包括等待 CPU 和等待 I/O 的进程。CPU使用率是单位时间内 CPU 繁忙情况的统计。
关系
CPU 密集型进程,使用大量 CPU 会导致平均负载升高,此时这两者是一致的;
I/O 密集型进程,等待 I/O 也会导致平均负载升高,但 CPU 使用率不一定很高;
大量等待 CPU 的进程调度也会导致平均负载升高,此时的 CPU 使用率也会比较高。
- 平均负载提供一个快速查看系统整体性能的手段,反映了整体的负载情况。单只看平均负载本身,并不能直接发现哪里出现了瓶颈
几点认识:
1. 平均负载高可能是CPU密集型进程导致的
2. 平均负载高并不一定代表CPU使用率高,还有可能是IO更繁忙了
3. 当负载高的时候,可以使用mpstat, pidstat等工具辅助分析负载的来源
- 进程在竞争 CPU 的时候并没有真正运行,为什么还会导致系统的负载升高呢?
CPU 上下文切换就是罪魁祸首
- CPU上下文
CPU寄存器 和 程序计数器PC
- CPU上下文切换
进程上下文件切换、线程上下文切换和中断上下文切换
- 系统调用
特权模式切换,也是CPU的上下文切换(1. 用户态切换到内核态; 2.内核态切换到用户态)
- 进程上下文切换
用户态(虚拟内存、栈、全局变量);内核态(CPU寄存器)
- 进程调度策略
进程就绪队列(活跃进程,优先级最高和等待CPU时间最长)
- 进程调度的场景
时间片
等待系统资源
sleep
高优先级抢占
中断
- 上下文切换的时间
几十纳秒到几微妙
- TLB
虚拟内存到物理内存的映射
- 线程上下文切换
线程是调度的基本单位,而进程是资源占用的基本单位。也就是一个进程中的线程是共享资源的。同进程内的线程切换比多进程间的线程切换消耗更少的资源。
- 中断上下文切换
不涉及到进程的用户态;中断比进程的优先级更高
- 怎么查看系统的上下文切换情况
vmstat - 查看系统整体情况; pidstat - 查看具体的进程情况
- 自愿上下文切换
进程无法获取所需资源导致的上下文切换,如IO、内存资源不足时
- 非自愿上下文切换
由于时间片已到等原因,被系统强制调度,进而发生的上下文切换,如大量进程争抢CPU
- 自愿上下文切换变多了,说明进程都在等待资源,有可能发生了 I/O 等其他问题;
vmstat
pidstat -wt
- 非自愿上下文切换变多了,说明进程都在被强制调度,也就是都在争抢 CPU,说明 CPU 的确成了瓶颈;
vmstat
pidstat -wt
- 中断次数变多了,说明 CPU 被中断处理程序占用,还需要通过查看 /proc/interrupts 文件来分析具体的中断类型。
cat /proc/interrupts
- CPU使用率
除了空闲时间外的其它时间占CPU总时间的百分比
- Linux的内核节拍率
可以查看Linux的节拍率的配置
$ grep 'CONFIG_HZ=' /boot/config-$(uname -r)
CONFIG_HZ=250
- 用户节拍率USER_HZ
始终为100
- Linux系统的CPU和任务的统计信息
通过命令查看/proc/stat中相关的信息
$ cat /proc/stat | grep ^cpu
cpu 280580 7407 286084 172900810 83602 0 583 0 0 0
cpu0 144745 4181 176701 86423902 52076 0 301 0 0 0
cpu1 135834 3226 109383 86476907 31525 0 282 0 0 0
- CPU使用率相关的重要指标
通过man proc命令查看
user(us) 用户态CPU时间,不包括nice时间,包括guest时间
nice(ni) 低优先级用户态CPU时间,优先级1~19
system(sys) 内核态CPU时间
idle(id) 空闲时间,不包括等待io的时间
iowait(wa) 等待磁盘IO的CPU时间
irq(hi) 处理硬中断的CPU时间
softirq(si) 处理软中断的CPU时间
steal(st) 系统运行在虚拟机中的时候,被其他虚拟机占用的CPU时间
guest(guest) 通过虚拟机运行其他操作系统的时间,也就是运行虚拟机的CPU时间
guest_nice(gnice) 以低优先级运行虚拟机的时间
- 每个进程的运行情况
通过命令查看/proc/[PID]/stat中的相关信息
- 性能分析工具给出的都是间隔一段时间的平均 CPU 使用率,所以要注意间隔时间的设置
- 通过工具可以确定CPU使用率过高的进程
top、ps、pidstat
- 如何确定CPU到底是在代码里的哪个函数呢?
GDB
不适合在性能分析的早期使用
不适合在线运行的程序
perf
需要安装
linux-tools-common
linux-tools-5.0.0-23-generic
目前的5.0的内核需要安装
per top
- 案例的精彩
使用docker镜像和github作为案例环境的准备很赞
- 案例的试炼
新版的ubuntu中的需要安装内核相关的perf工具,而工具使用存在BUG。需要考虑对应内核版本的工具,而且perf -p命令有问题,于是使用perf record记录所有进程的信息后,通过perf report打印结果,同样可以分析出文中的结论。
- 案例分析经验
用户CPU和Nice CPU高,说明用户态进程占用了较多的CPU,应该着重排查应用进程的性能问题
系统CPU高,说明内核态占用了较多的CPU,应该着重排查内核形成或者系统调用的性能问题
IO等待CPU高,说明等待IO的时间比较长,应该着重排查系统存储是不是出现了IO问题
软中断和硬中断高,说明软中断或硬中断处理程序占用了较多的CPU,应该着重排查内核的中断服务程序
- 思考:我所理解的CPU使用率
我排查过进程CPU使用过高的问题,通过top发现进程的CPU使用超过100%后,进一步通过ps命令和pstack命令获得CPU超过100%的线程,进一步分析线程逻辑代码,解决问题
- 当你发现系统的 CPU 使用率很高的时候,不一定能找到相对应的高 CPU 使用率的进程。
本章的案例着实比较难找,如果不是顺着作者的思路,估计我无法找到其中的端倪
- 案例的试炼
如果服务端不支持verbose输出错误信息,那么查错的难度将大大增加。 只能进一步分析服务端的日志。
通过perf工具的记录无法分析出调用最多的random函数。
可能和我使用的虚拟机的性能不够有关
如何修复权限问题?
进入到容器中,检查/app的目录权限,可以发现daemon用户没有写权限
可以通过chmod a+w /app来修复权限问题,修复后再次进行压测时,CPU使用率明显降低
execsnoop使用无输出
- 案例分析经验
碰到常规问题无法解释的CPU使用率情况时,要想到是短时进程导致的
1. 应用里直接调用了其他二进制程序,这些程序通常运行时间比较短,通过 top 等工具也不容易发现。
2. 应用本身在不停地崩溃重启,而启动过程的资源初始化,很可能会占用相当多的 CPU。
- 从进程状态看系统问题
不可中断进程
如果系统或硬件发生故障,进程可能长时间处于不可中断状态,或大量不可中断进程
僵尸进程
多进程应用常见问题
- ps进程附加状态
s 一个会话的领导进程
+ 进程在前台进程组中
- 进程组
一组相互关联的进程,比如每个子进程都是父进程所在组的成员
- 会话
共享同一个控制终端的一个或多个进程组
- 案例的试炼
性能工具的输出要仔细看,每个数据都不能放过。可能不经意间就有漏掉的内容
iowait高的分析思路
使用iowait查看导致io高的进程
大量的app进程读操作后退出
如何确定具体的读操作?
- iowait分析
使用dstat工具,可以同时查看CPU和IO
dstat 1 10
--total-cpu-usage-- -dsk/total- -net/total- ---paging-- ---system--
usr sys idl wai stl| read writ| recv send| in out | int csw
5 1 92 1 0| 19M 445k| 0 0 | 28B 138B| 355 600
5 1 94 0 0| 0 0 | 0 0 | 0 0 | 203 349
7 9 39 45 0| 437M 0 | 0 0 | 0 0 |1002 1410
6 2 2 91 0| 326M 0 | 0 0 | 0 0 | 839 1158
12 21 10 57 0|1797M 0 | 0 0 | 0 0 |3761 4255
7 1 92 0 0| 0 0 | 0 0 | 0 0 | 183 348
7 1 89 3 0| 0 36k| 0 0 | 0 0 | 280 443
10 8 40 42 0| 433M 0 | 0 0 | 0 0 |1272 1518
6 1 18 76 0| 341M 0 | 0 0 | 0 0 | 915 1255
11 18 43 28 0|1785M 0 | 0 0 | 0 0 |3383 4002
- 案例的试炼
性能工具的输出异常,需要多个工具相互印证
如何确定具体的读操作?
通过perf工具
和我的思路一致
如何找出父进程? pstree
- 案例分析经验
iowait 高不一定代表 I/O 有性能瓶颈。当系统中只有 I/O 类型的进程在运行时,iowait 也会很高,但实际上,磁盘的读写远没有达到性能瓶颈的程度。
分析思路
IO问题
先用 dstat、pidstat 等工具,确认是不是磁盘 I/O 的问题,然后再找是哪些进程导致了 I/O。
ps 命令找到的 D 状态(即不可中断状态)的进程,多为可疑进程。
perf 工具,来分析系统的 CPU 时钟事件,最终发现是直接 I/O 导致的问题。
僵尸进程
pstree 找出父进程
- 中断
系统用来响应硬件设备请求的一种机制,是一种异步的事件处理机制,可以提高系统的并发处理能力
打断进程的正常调度和执行,调用内核中的中断处理程序来响应设备请求
打电话”就是一个中断
- 关中断
可能导致中断丢失
- 中断处理
上半部
快速处理中断, 与硬件紧密相关或时间敏感 下半部 延迟处理上半部未完成的工作, 通常以内核线程的方式
- 软中断
常见的软中断
硬件设备中断处理程序的下半部 内核自定义事件:内核调度和RCU锁
- RCU锁
Read-Copy Update
-
软中断(softirq)CPU使用率升高也是最常见的一种性能问题
-
/proc/softirqs
$ cat /proc/softirqs
CPU0 CPU1
HI: 5 53
TIMER: 1743976 1836151
NET_TX: 16859 2467
NET_RX: 1734132 1605776
BLOCK: 1062689 1134048
IRQ_POLL: 0 0
TASKLET: 22455 324
SCHED: 1097794 1186038
HRTIMER: 0 0
RCU: 1663427 1816295
- 有没有碰到过因为软中断出现的性能问题呢?
还没有碰到过,或者碰到了也没有查出是软中断的问题。
- sar
系统活动报告工具
- hping3
可以构造TCP/IP协议数据包的工具
安全审计
防火墙测试
- tcpdump
常用的网络抓包工具
- 案例的试炼
系统并没有因为软中断多而卡顿
需要格外注意多个指标的共同分析
网络包的数量和网络流量对比发现每个网络包的数量很小
- 案例分析经验
从top入手发现软中断问题,分析软中断类型发现是网络收发类型的中断,通过sar、tcpdump进一步分析
- 理论 - 实践 - 理论
从基础理论到实践,再回到更高层次的理论
哲学指导人生
- CPU使用率
用户CPU使用率
user nice
系统CPU使用率
sys
等待I/O的CPU使用率
iowait
软中断和硬中断的CPU使用率
其它
虚拟化 steal guest
- 平均负载
进程上下文切换
自愿上下文切换 非自愿上下文切换
CPU缓存命中率
- CPU缓存命中率
- uptime
查看系统的平均负载
- mpstat
观察每个CPU的使用情况
- pidstat
观察每个进程CPU的使用情况
查看自愿上下文切换和非自愿上下文切换的情况
- vmstat
查看系统上下文切换次数和中断次数
- top
查看系统和进程CPU使用情况
查看iowait升高的问题
- perf
查找性能热点 top record report
- execsnoop
短时进程 调用外部命令
- dstat
类似与vmstat的增强版
- strace
查看系统的进程调用
- /proc/softirqs
查看软中断
- sar
查看网络包问题
- tcpdump
网络抓包
- stress
压力测试
- sysbench
基准测试
- hping3
网络报文
- 第一个维度,从CPU的性能指标触发。也就是说,当你要查看某个性能指标时,要清楚知道哪些工具可以做到
- 第二个维度,从工具出发。也就是当你已经安装了某个工具后,要知道这个工具能提供哪些指标。
- 要弄清除性能指标的关联性,就要通晓每种性能指标的工作原理
为了缩小排查范围,通常会先运行几个支持指标较多的工具 如top、vmstat和pidstat
-
第一个问题:性能优化是否有效? 优化后,能够提升多少性能
-
三个步骤
1.确定性能的量化指标
2.测试优化前的性能指标
3.测试优化后的性能指标
- 两个维度
应用程序
吞吐量
请求延迟
系统资源
CPU使用率
- 性能测试的问题
避免性能测试工具干扰应用程序的性能
避免外部环境的变化影响性能指标的评估
第二个问题:多个性能问题同时发生、应该先优化哪一个?
- 二八原则
并不是所有的性能问题都值得优化
- 如何判断那个性能问题最重要
因果分析,排除掉因果关联的性能问题
剩下的问题性能优化
逐个测试,选择明显提升性能的问题
- 简化过程
系统资源达到瓶颈,首先优化
首先优化有瓶颈导致,指标变化幅度最大的问题
第三个问题:选择哪一种性能优化的方法? 是否总选最大程度提升性能的方法?
- 性能优化并非没有成本
复杂度提升、可维护性降低
优化一个指标,另一个指标变差
综合考虑
- CPU优化
应用程序优化
编译器优化
算法优化
异步处理
多线程替代多进程
善用缓存
系统优化
CPU绑定
CPU独占
优先级调整
为进程设置资源限制
NUMA优化
中断负载均衡
- 千万避免过早优化
过早优化是万恶之源
- 查看proc文件系统获取缺失指标
- 处理器间中断(Inter-Processor Interrupts,IPI)
- 每个人的机器配置不同
- docker logs 查看它的日志
- 在碰到直观上解释不了的现象时,要第一时间去查命令手册。
- perf找不到待分析进程依赖的库
四个解决方法
在容器外面构建相同路径的依赖库
在容器内运行perf
需要容器运行在特权模式下
指定符号路径为容器文件系统的路径
bindfs
在容器外面把分析记录保存下来,再在容器里查看结果
-
perf_events
-
技术博客《Java in Flames》
https://medium.com/netflix-techblog/java-in-flames-e763b3d32166
还是多学习文档
- swapper
- Children vs Self
- 动态追踪工具带来性能损失
- 《Systems Performance: Enterprise and the Cloud》