Skip to content

Latest commit

 

History

History
692 lines (529 loc) · 23 KB

File metadata and controls

692 lines (529 loc) · 23 KB

《Linux性能优化实战》学习笔记

在上下班路上粗听了一遍倪朋飞老师的这个系列课程,让我弄清了很多原来似是而非的基本概念。所以,打算集中一段时间好好学习一下这个系列的课程,实际操作一下课程中的例子,并将心得体会记录在本文中。

课程连接: Linux性能优化实战

开篇词 | 别再让Linux性能问题成为你的绊脚石

  • 把观察到的性能问题跟系统原理关联起来,特别是把系统从应用程序、库函数、系统调用、再到内核和硬件等不同的层级贯穿起来。

在学习这个系列课程之前,我处理现场的性能问题时大都靠临时的搜索去完成,通过搜索引擎搜索到的东西零碎不成体系,有时后可以能够发挥作用,常常需要不断的去尝试不同的解决方案。解决问题后,有时也不能了解其中的原理。我想这就是没有贯通,没有从上到下打通问题从现象到本质,再到原理的路径,犹如习练武功,外功招式多,经脉未打通,内力有限。希望通过这个系列的课程,打通性能的任督二脉,内力更上一个台阶。

  • 性能优化是个系统工程,总是牵一发而动全身。

众里寻她千百度。

  • 性能优化是软件系统中最有挑战的工作之一,但是换个角度看,它也是最考验体现你综合能力的工作之一。

  • 最好的学习方式一定是带着问题学习。

就是有目的的学习。

  • 想要得到你就要学会付出,要付出还要坚持;如果你真的觉得很难,那你就放弃,如果你放弃了就不要抱怨。人生就是这样,世界是平衡的,每个人都是通过自己的努力,去决定自己生活的样子。

选择、努力。

01 | 如何学习Linux性能优化?

  • 建立起整体性能的全局观

理解原理,进行实践,也就是理论联系实际,知行合一。

  • 性能指标是什么?

我们谈及性能,自然要明白性能的基本概念。性能指标就是观察性能的角度和衡量的标准。 文中从两个视角去观察性能: 一是应用的视角,即应用负载的指标,表示应用用了多少?;另一个是系统的视角,即系统资源的指标,表示还能用多少? 性能问题的本质是应用负载的增加导致系统资源达到瓶颈,这两者本来就是一对矛盾体,此消彼长。

  • 解决性能问题的步骤:

六个步骤:

    1.选择指标评估应用程序和系统的性能
    2.为应用程序和系统设置性能目标
    3.进行性能基准测试
    4.性能分析定位瓶颈
    5.优化系统和应用程序
    6.性能监控和告警 
  • 学习的重点是什么?

“道”:理解最基本的几个系统知识原理;“器”:掌握必要的性能工具;“运用”:通过实际的场景演练,贯穿不同的组件

  • 布伦丹·格雷格

大师,膜拜 网站Linux Performance

  • 千万不要把性能工具当成学习的全部

工具是器,更重要的是掌握道

  • 如何高效学习

技巧一:不要试图抓住所有的实现细节,抓重点,20-80原则;技巧二:边学边实践,知行合一;技巧三:勤思考、多反思、善总结,多问为什么

02 | 基础篇:到底应该怎么理解“平均负载”?

  • 平均负载

可以通过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等工具辅助分析负载的来源

03 | 基础篇:经常说的 CPU 上下文切换是什么意思?(上)

  • 进程在竞争 CPU 的时候并没有真正运行,为什么还会导致系统的负载升高呢?

CPU 上下文切换就是罪魁祸首

  • CPU上下文

CPU寄存器 和 程序计数器PC

  • CPU上下文切换

进程上下文件切换、线程上下文切换和中断上下文切换

  • 系统调用

特权模式切换,也是CPU的上下文切换(1. 用户态切换到内核态; 2.内核态切换到用户态)

  • 进程上下文切换

用户态(虚拟内存、栈、全局变量);内核态(CPU寄存器)

  • 进程调度策略

进程就绪队列(活跃进程,优先级最高和等待CPU时间最长)

  • 进程调度的场景
    时间片
    等待系统资源
    sleep
    高优先级抢占
    中断
  • 上下文切换的时间

几十纳秒到几微妙

  • TLB

虚拟内存到物理内存的映射

  • 线程上下文切换

线程是调度的基本单位,而进程是资源占用的基本单位。也就是一个进程中的线程是共享资源的。同进程内的线程切换比多进程间的线程切换消耗更少的资源。

  • 中断上下文切换

不涉及到进程的用户态;中断比进程的优先级更高

04 | 基础篇:经常说的 CPU 上下文切换是什么意思?(下)

  • 怎么查看系统的上下文切换情况

vmstat - 查看系统整体情况; pidstat - 查看具体的进程情况

  • 自愿上下文切换

进程无法获取所需资源导致的上下文切换,如IO、内存资源不足时

  • 非自愿上下文切换

由于时间片已到等原因,被系统强制调度,进而发生的上下文切换,如大量进程争抢CPU

案例分析经验

  • 自愿上下文切换变多了,说明进程都在等待资源,有可能发生了 I/O 等其他问题;
    vmstat
    pidstat -wt
  • 非自愿上下文切换变多了,说明进程都在被强制调度,也就是都在争抢 CPU,说明 CPU 的确成了瓶颈;
    vmstat
    pidstat -wt
  • 中断次数变多了,说明 CPU 被中断处理程序占用,还需要通过查看 /proc/interrupts 文件来分析具体的中断类型。
    cat /proc/interrupts

05 | 基础篇:某个应用的CPU使用率居然达到100%,我该怎么办?

  • 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使用率过高怎么办?

  • 通过工具可以确定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%的线程,进一步分析线程逻辑代码,解决问题

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

  • 当你发现系统的 CPU 使用率很高的时候,不一定能找到相对应的高 CPU 使用率的进程。

本章的案例着实比较难找,如果不是顺着作者的思路,估计我无法找到其中的端倪

案例

  • 案例的试炼

如果服务端不支持verbose输出错误信息,那么查错的难度将大大增加。 只能进一步分析服务端的日志。

通过perf工具的记录无法分析出调用最多的random函数。

    可能和我使用的虚拟机的性能不够有关

如何修复权限问题?

    进入到容器中,检查/app的目录权限,可以发现daemon用户没有写权限
        可以通过chmod a+w /app来修复权限问题,修复后再次进行压测时,CPU使用率明显降低

execsnoop使用无输出

  • 案例分析经验

碰到常规问题无法解释的CPU使用率情况时,要想到是短时进程导致的

    1. 应用里直接调用了其他二进制程序,这些程序通常运行时间比较短,通过 top 等工具也不容易发现。
    2. 应用本身在不停地崩溃重启,而启动过程的资源初始化,很可能会占用相当多的 CPU。

07 | 案例篇:系统中出现大量不可中断进程和僵尸进程怎么办?(上)

  • 从进程状态看系统问题

不可中断进程

    如果系统或硬件发生故障,进程可能长时间处于不可中断状态,或大量不可中断进程

僵尸进程

    多进程应用常见问题
  • ps进程附加状态

s 一个会话的领导进程

+ 进程在前台进程组中

  • 进程组

一组相互关联的进程,比如每个子进程都是父进程所在组的成员

  • 会话

共享同一个控制终端的一个或多个进程组

案例

  • 案例的试炼

性能工具的输出要仔细看,每个数据都不能放过。可能不经意间就有漏掉的内容

iowait高的分析思路

    使用iowait查看导致io高的进程
        大量的app进程读操作后退出
    如何确定具体的读操作?

08 | 案例篇:系统中出现大量不可中断进程和僵尸进程怎么办?(下)

  • 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 找出父进程

09 | 基础篇:怎么理解Linux软中断?

  • 中断

系统用来响应硬件设备请求的一种机制,是一种异步的事件处理机制,可以提高系统的并发处理能力

打断进程的正常调度和执行,调用内核中的中断处理程序来响应设备请求

打电话”就是一个中断

  • 关中断

可能导致中断丢失

  • 中断处理

上半部

快速处理中断, 与硬件紧密相关或时间敏感 下半部 延迟处理上半部未完成的工作, 通常以内核线程的方式

  • 软中断

常见的软中断

硬件设备中断处理程序的下半部 内核自定义事件:内核调度和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
  • 有没有碰到过因为软中断出现的性能问题呢?

还没有碰到过,或者碰到了也没有查出是软中断的问题。

10 | 案例篇:系统的软中断CPU使用率升高,我该怎么办?

  • sar

系统活动报告工具

  • hping3

可以构造TCP/IP协议数据包的工具

安全审计

防火墙测试

  • tcpdump

常用的网络抓包工具

案例

  • 案例的试炼

系统并没有因为软中断多而卡顿

需要格外注意多个指标的共同分析

网络包的数量和网络流量对比发现每个网络包的数量很小

  • 案例分析经验

从top入手发现软中断问题,分析软中断类型发现是网络收发类型的中断,通过sar、tcpdump进一步分析

11 | 套路篇:如何迅速分析出系统CPU的瓶颈在哪里?

  • 理论 - 实践 - 理论

从基础理论到实践,再回到更高层次的理论

哲学指导人生

CPU性能指标

  • CPU使用率

用户CPU使用率

user nice

系统CPU使用率

sys

等待I/O的CPU使用率

iowait

软中断和硬中断的CPU使用率

其它

虚拟化 steal guest

  • 平均负载

进程上下文切换

自愿上下文切换 非自愿上下文切换

CPU缓存命中率

  • 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的性能指标触发。也就是说,当你要查看某个性能指标时,要清楚知道哪些工具可以做到

根据指标找工具

  • 第二个维度,从工具出发。也就是当你已经安装了某个工具后,要知道这个工具能提供哪些指标。

根据工具找指标

如何迅速分析CPU的性能瓶颈

  • 要弄清除性能指标的关联性,就要通晓每种性能指标的工作原理

为了缩小排查范围,通常会先运行几个支持指标较多的工具 如top、vmstat和pidstat

多工具联合排查

12 | 套路篇:CPU 性能优化的几个思路

性能优化方法论

评估性能优化的效果

  • 第一个问题:性能优化是否有效? 优化后,能够提升多少性能

  • 三个步骤

1.确定性能的量化指标

2.测试优化前的性能指标

3.测试优化后的性能指标

  • 两个维度

应用程序

    吞吐量
    请求延迟

系统资源

    CPU使用率
  • 性能测试的问题
  1. 避免性能测试工具干扰应用程序的性能

  2. 避免外部环境的变化影响性能指标的评估

多个性能问题同时存在,要怎么选择?

第二个问题:多个性能问题同时发生、应该先优化哪一个?

  • 二八原则

并不是所有的性能问题都值得优化

  • 如何判断那个性能问题最重要
  1. 因果分析,排除掉因果关联的性能问题

  2. 剩下的问题性能优化

    逐个测试,选择明显提升性能的问题
  • 简化过程
  1. 系统资源达到瓶颈,首先优化

  2. 首先优化有瓶颈导致,指标变化幅度最大的问题

有多种方法时,要如何选择?

第三个问题:选择哪一种性能优化的方法? 是否总选最大程度提升性能的方法?

  • 性能优化并非没有成本

复杂度提升、可维护性降低

优化一个指标,另一个指标变差

综合考虑
  • CPU优化

应用程序优化

编译器优化
算法优化
异步处理
多线程替代多进程
善用缓存

系统优化

CPU绑定
CPU独占
优先级调整
为进程设置资源限制
NUMA优化
中断负载均衡
  • 千万避免过早优化

过早优化是万恶之源

13 | 答疑(一):无法模拟出 RES 中断的问题,怎么办?

问题 1:性能工具版本太低,导致指标不全

  • 查看proc文件系统获取缺失指标

问题 2:使用 stress 命令,无法模拟 iowait 高的场景

问题 3:无法模拟出 RES 中断的问题

  • 处理器间中断(Inter-Processor Interrupts,IPI)

问题 4:无法模拟出 I/O 性能瓶颈,以及 I/O 压力过大的问题

  • 每个人的机器配置不同
  • docker logs 查看它的日志

问题 5:性能工具(如 vmstat)输出中,第一行数据跟其他行差别巨大

  • 在碰到直观上解释不了的现象时,要第一时间去查命令手册。

14 | 答疑(二):如何用perf工具分析Java程序?

问题 1: 使用 perf 工具时,看到的是 16 进制地址而不是函数名

  • perf找不到待分析进程依赖的库

四个解决方法

在容器外面构建相同路径的依赖库
在容器内运行perf
    需要容器运行在特权模式下
指定符号路径为容器文件系统的路径
    bindfs
在容器外面把分析记录保存下来,再在容器里查看结果

问题 2:如何用 perf 工具分析 Java 程序

  • perf_events

  • 技术博客《Java in Flames》

https://medium.com/netflix-techblog/java-in-flames-e763b3d32166

问题 3:为什么 perf 的报告中,很多符号都不显示调用栈

还是多学习文档

问题 4:怎么理解 perf report 报告

  • swapper
  • Children vs Self
  • 动态追踪工具带来性能损失

问题 5:性能优化书籍和参考资料推荐

  • 《Systems Performance: Enterprise and the Cloud》