Linux 性能分析最重要的参考资料
todo 13,14
一、CPU性能
平均负载
简单理解为,平均负载其实就是平均活跃进程数(包括等待cpu的进程)
比如当平均负载为 2 时,意味着什么呢?
在只有 2 个 CPU 的系统上,意味着所有的 CPU 都刚好被完全占用。
在 4 个 CPU 的系统上,意味着 CPU 有 50% 的空闲。
而在只有 1 个 CPU 的系统中,则意味着有一半的进程竞争不到 CPU
一般当平均负载高于 CPU 数量 70% 的时候,你就应该分析排查负载高的问题了
上下文
CPU 都需要知道任务从哪里加载、又从哪里开始运行,也就是说,需要系统事先帮它设置好 CPU上下文(CPU 寄存器和程序计数器)
定义
CPU 上下文切换,就是先把前一个任务的 CPU 上下文(也就是 CPU 寄存器和程序计数器)保存起来,然后加
载新任务的上下文到这些寄存器和程序计数器,最后再跳转到程序计数器所指的新位置,
运行新任务。
场景
- 进程上下文切换、
进程的切换只能发生在内核态,进程的上下文切换就比系统调用时多了一步:需要先把该进程的虚拟内存、栈等保存下来,再保存当前进程的内核状态和 CPU 寄存器,;而加载了下一进程的内核态后,还需要刷新进程的虚拟内存和用户栈。
根据 Tsuna 的测试报告,每次上下文切换都需要几十纳秒到数微秒的 CPU 时间 - 线程上下文切换(线程与进程最大的区别在于,线程是调度的基本单位,而进程则是资源拥有的基本单位)
线程的上下文切换其实可以分为两种情况:
第一种, 前后两个线程属于不同进程。此时,因为资源不共享,所以切换过程就跟进程上下文切换是一样。
第二种,前后两个线程属于同一个进程。此时,因为虚拟内存是共享的,所以在切换时,虚拟内存这些资源就保持不动,只需要切换线程的私有数据、寄存器等不共享的数据 - 中断上下文切换。
跟进程上下文不同,中断上下文切换并不涉及到进程的用户态。所以,即便中断过程打断了一个正处在用户态的进程,也不需要保存和恢复这个进程的虚拟内存、全局变量等用户态资源。中断上下文,其实只包括内核态中断服务程序执行所必需的状态,包括 CPU 寄存
器、内核堆栈、硬件中断参数等。
系统调用,需要用户态内核态切换,所以,一次系统调用的过程,其实是发生了两次 CPU 上下文切换,系统调用过程中一直是同一个进程在运行,跟我们通常所说的进程上下文切换是不一样的,通常称为特权模式切换
自愿上下文切换:是指进程无法获取所需资源,导致的上下文切换。比如说, I/O、内存等系统资源不足时,就会发生自愿上下文切换。
非自愿上下文切换:则是指进程由于时间片已到等原因,被系统强制调度,进而发生 的上下文切换。比如说,大量进程都在争抢 CPU
时,就容易发生非自愿上下文切换
cpu使用率 & 命令
查看cpu使用率过高的进程
top (总体,有细分进程的用户态 CPU 和内核态 CPU)
ps 则只显示了每个进程的资源使用情况
ps -aux|grep java
pidstat (每个进程的详细情况,用户态 CPU 和内核态 CPU)
分析cpu问题
perf top 实时展示了系统的性能信息(各个函数占用cpu时钟数)
perf record 则提供了保存数据的功能
perf report 解析展示保存后的数据
== cpu问题:借助 top、pidstat 等工具,确认引发 CPU 性能问
题的来源;再使用 perf 等工具,排查出引起性能问题的具体函数==
top 并没有细分进程的用户态 CPU 和内核态 CPU。那要怎么查看每个进程的详细情况呢
pidstat 1 5:pidstat 命令,就间隔 1 秒展示了进程的 5 组 CPU 使用率
pidstat 1 5
再使用 perf top 工具,定位应用内部函数的问题
请求某个接口
并发 10 个请求测试 Nginx 性能,总共测试 100 个请求
ab -c 10 -n 100 http://192.168.0.10:8080/
查看哪个代码导致cpu使用率100%(部署个项目模拟下)
请求服务,查看能承受请求数
ab -c 10 -n 100 http://10.101.38.18:8080/(并发 10 个请求测试 Nginx 性能,总共测试 100 个请求)
top查看cpu使用率
perf top -g -p 21515(-g 开启调用关系分析,-p 指定进程号)
按方向键切换到 java进程,再按下回车键展开调用关系
用户 CPU 和 Nice CPU 高,说明用户态进程占用了较多的 CPU,所以应该着重排查进 程的性能问题。
系统 CPU高,说明内核态占用了较多的 CPU,所以应该着重排查内核线程或者系统调 用的性能问题。
I/O 等待 CPU 高,说明等待 I/O的时间比较长,所以应该着重排查系统存储是不是出现 了 I/O 问题。
软中断和硬中断高,说明软中断或硬中断的处理程序占用了较多的CPU,所以应该着重 排查内核中的中断服务程序。
cpu升高top等命令却看不到
可能是短时进程导致的,短时应用的运行时间比较短,很难在 top 或者 ps 这类展示系统概要和进程快照的工具中发现
进程状态
top ,可以查看进程的状态,这些状态包括运行(R)、空闲(I)、不可中断状态(D)、可中断睡眠(S)、僵尸(Z)以及暂停(T)等
不可中断状态,表示进程正在跟硬件交互,为了保护进程数据和硬件的一致性,系统不允许其他进程或中断打断这个进程。进程长时间处于不可中断状态,通常表示系统有 I/O 性能问题。
僵尸进程表示进程已经退出,但它的父进程还没有回收子进程占用的资源。短暂的僵尸 状态我们通常不必理会,但进程长时间处于僵尸状态,就应该注意了,可能有应用程序 没有正常处理子进程的退出。
io升高
iowait 高不一定代表 I/O 有性能瓶
颈。当系统中只有 I/O 类型的进程在运行时,iowait 也会很高,但实际上,磁盘的读写远
没有达到性能瓶颈的程度。
因此,碰到 iowait 升高时,需要先用 dstat、pidstat 等工具,确认是不是磁盘 I/O 的问
题,然后再找是哪些进程导致了 I/O。
等待 I/O 的进程一般是不可中断状态,所以用 ps 命令找到的 D 状态(即不可中断状态)
的进程,多为可疑进程。但这个案例中,在 I/O 操作后,进程又变成了僵尸进程,所以不
能用 strace 直接分析这个进程的系统调用。
这种情况下,我们用了 perf 工具,来分析系统的 CPU 时钟事件,最终发现是直接 I/O 导
致的问题。这时,再检查源码中对应位置的问题,就很轻松了。
僵尸进程如何处理
是找出父进程,然后在父进程里解决。
父进程的找法,就是运行 pstree 命令
-a 表示输出命令行选项 p 表 PID s 表示指定进程的父进程
$ pstree -aps 3084
而僵尸进程的问题相对容易排查,使用 pstree 找出父进程后,去查看父进程的代码,检查
wait() / waitpid() 的调用,或是 SIGCHLD 信号处理函数的注册就行了。
软中断(类比送外卖,打电话(硬中断),处理其他发票(软中断))
中断其实是一种异步的事件处理机制,可以提高系统的并发处理能力。
由于中断处理程序会打断其他进程的运行,所以,为了减少对正常进程运行调度的影响,中断处理程序就需要尽可能快地运行
中断处理程序在响应中断时,还会临时关闭中断。这就会导致上一次中断处理完成之前,其他中断都不能响应,也就是说中断有可能会丢失。
软中断实际上是以内核线程的方式运行的,Linux 中的软中断包括网络收发、定时、调度、RCU 锁等各种类型,可以通过查看
/proc/softirqs 来观察软中断的运行情况。
Linux 中的中断处理程序分为上半部和下半部:
上半部对应硬件中断,用来快速处理中断。,特点是快速执行
下半部对应软中断,用来异步处理上半部未完成的工作。,特点是延迟执行
网卡接收到数据包后,会通过硬件中断的方式,通知内核有新的数据到了。这时,内核就
应该调用中断处理程序来响应它。你可以自己先想一下,这种情况下的上半部和下半部分 别负责什么工作呢?
对上半部来说,既然是快速处理,其实就是要把网卡的数据读到内存中,然后更新一下硬
件寄存器的状态(表示数据已经读好了),最后再发送一个软中断信号,通知下半部做进 一步的处理。
而下半部被软中断信号唤醒后,需要从内存中找到网络数据,再按照网络协议栈,对数据 进行逐层解析和处理,直到把它送给应用程序。
看10,
如何快速分析cpu问题(top、vmstat和 pidstat)
性能指标
性能工具
- 第一个维度,从 CPU 的性能指标出发。也就是说,当你要查看某个性能指标时,要清楚知道哪些工具可以做到
2. 第二个维度,从工具出发。也就是当你已经安装了某个工具后,要知道这个工具能提供哪些指标。
二、内存性能
查看内存使用
可以用 free 和 top 、ps 等性能工具
内存
进程来说,它能看到的其实是内核提供的虚拟内存,虚拟地址空间的内部又被分为内核空间和用户空间
虽然每个进程的地址空间都包含了内核空间,但这些内核空间,其实关联的都是相同的物理内存
并不是所有的虚拟内存都会分配物理内存,只有那些实际使用的虚拟内存才分配物理内存,并且分配后的物理内存,是通过内存映射来管理的
虚拟内存分布
Swap
其实就是把一块磁盘空间当成内存来用。它可以把进程暂时不用的数据存储到磁盘中(这
个过程称为换出),当进程访问这些内存时,再从磁盘读取这些数据到内存中(这个过程
称为换入)。
查看内存使用(free, top,(M按内存排序),ps)
top
VIRT 是进程虚拟内存的大小,只要是进程申请过的内存,即便还没有真正分配物理内存,也会计算在内。
RES 是常驻内存的大小,也就是进程实际使用的物理内存大小,但不包括 Swap 和共享内存。
SHR 是共享内存的大小,比如与其他进程共同使用的共享内存、加载的动态链接库以及程序的代码段等。
%MEM 是进程使用物理内存占系统总内存的百分比。
buffer & cache
Buffers (对将要写入磁盘数据的缓存)是对原始磁盘块的临时存储,也就是用来缓存磁盘的数据,通常不会特别大(20MB 左右)。这样,内核就可以把分散的写集中起来,统一优化磁盘的写入,比如可以把多次小的写合并成单次大的写等等。
Cached 是从磁盘读取文件的页缓存,也就是用来缓存从文件读取的数据。这样,下次访问这些文件数据时,就可以直接从内存中快速获取,而不需要再次访问缓慢的磁盘。
写磁盘用到了大量的 Buffer,Buffer 和 Cache 都在增长
写文件时会用到 Cache 缓存数据
Buffer 是对磁盘数据的缓存,而 Cache 是文件数据的缓存,它们既会用在读请求中,也会用在写请求中。
读写普通文件时,会经过文件系统,由文件系统负责与磁盘交互;而读写磁盘或者分区时,就会跳过文件系统,也就是所谓的“裸I/O“。这两种读写方式所使用的缓存是不同的,也就是文中所讲的
Cache 和 Buffer 区别。
内存泄露了该如何定位处理
应用程序可以访问的用户内存空间,由只读段、数据段、堆、栈以及文件映射段等组成。
其中,堆内存和内存映射,需要应用程序来动态管理内存段,所以我们必须小心处理
vmstat 观察free在减少
/usr/share/bcc/tools/memleak -a -p $(pidof app)(跟踪系统或指定进程的内存分配、释放请求)
swap(内存数据存储到磁盘中)
笔记本电脑的休眠和快速开机的功能,也基于 Swap
在内存资源紧张时,Linux 通过直接内存回收和定期扫描的方式,来释放文件页和匿名页,以便把内存分配给更需要的进程使用。
文件页(缓存和缓冲区)的回收比较容易理解,直接清空,或者把脏数据写回磁盘后再释放。
而对匿名页的回收(应用程序动态分配的堆内存),需要通过 Swap 换出到磁盘中,下次访问时,再从磁盘换入到内存中。
free可以查看swap的使用情况
三、I/O性能
文件系统
索引节点和目录项
磁盘为系统提供了最基本的持久化存储。
文件系统则在磁盘的基础上,提供了一个用来管理文件的树状结构
Linux 文件系统为每个文件都分配两个数据结构,索引节点(indexnode)和目录项(directory entry)
目录项,简称为 dentry,用来记录文件的名字、索引节点指针以及与其他目录项的关联关系。多个关联的目录项,就构成了文件系统的目录结构,换句话说,索引节点是每个文件的唯一标志,而目录项维护的正是文件系统的树状结构。目录项和索引节点的关系是多对一
虚拟文件系统
不同文件系统
- 基于磁盘的文件系统(如:ext4)
- 基于内存的文件系统(如:/proc)
- 网络文件系统(如:/nfs)
挂载到/根目录下才能使用,把文件系统挂载到挂载点后,你就能通过挂载点,再去访问它管理的文件了
“Linux 一切皆文件”的深刻含义。无论是普通文件和块设备、还是网络套接字和管道等,它们都通过统一的 VFS 接口来访问。
磁盘I/O
其实在 Linux 中,磁盘实际上是作为一个块设备来管理的,也就是以块为单位读写数据,并且支持随机读写
通用块层
和虚拟文件系统 VFS 类似,为了减小不同块设备(磁盘)的差异带来的影响,Linux 通过一个统一的通用块层,来管理各种不同的块设备。
I/O 栈
文件系统层,包括虚拟文件系统和其他各种文件系统的具体实现。它为上层的应用程序,提供标准的文件访问接口;对下会
通过通用块层,来存储和管理磁盘数据。(屏蔽不同文件系统,磁盘,内存、网络)
通用块层,包括块设备 I/O 队列和 I/O 调度器。它会对文件系统的 I/O 请求进行排队,再通过重新排序和请求合并,然后才
要发送给下一级的设备层。(屏蔽不同块设备(磁盘))
设备层,包括存储设备和相应的驱动程序,负责最终物理设备的 I/O 操作。
磁盘性能指标(25,操作)
使用率,是指磁盘处理 I/O 的时间百分比。过高的使用率(比如超过 80%),通常意味着磁盘 I/O 存在性能瓶颈。
饱和度,是指磁盘处理 I/O 的繁忙程度。过高的饱和度,意味着磁盘存在严重的性能瓶颈。当饱和度为 100% 时,磁盘无法接受新的 I/O 请求
IOPS(Input/Output Per Second),是指每秒的 I/O 请求数。
吞吐量,是指每秒的 I/O 请求大小。
响应时间,是指 I/O 请求从发出到收到响应的间隔时间。
在数据库、大量小文件等这类随机读写比较多的场景中,IOPS 更能反映系统的整体性能
在多媒体等顺序读写较多的场景中,吞吐量才更能反映系统的整体性能。
四、网络性能
基础
在 Linux 中,我们实际上使用的是另一个更实用的四层模型,即 TCP/IP 网络模型
封装
过程
网络性能指标(34 操作)
带宽,表示链路的最大传输速率,单位通常为 b/s (比特 / 秒)。
吞吐量,表示单位时间内成功传输的数据量,单位通常为 b/s(比特 / 秒)或者B/s(字节 / 秒)。吞吐量受带宽限制,而吞吐量 / 带宽,也就是该网络的使用率。
延时,表示从网络请求发出后,一直到收到远端响应,所需要的时间延迟。在不同场景中,这一指标可能会有不同含义。比如,它可以表示,建立连接需要的时间(比如 TCP握手延时),或一个数据包往返所需的时间(比如 RTT)。
PPS,是 Packet Per Second(包 / 秒)的缩写,表示以网络包为单位的传输速率。PPS 通常用来评估网络的转发能力,比如硬件交换机,通常可以达到线性转发(即 PPS
可以达到或者接近理论最大值)。而基于 Linux 服务器的转发,则容易受网络包大小的影响。
C10,C1000问题(epoll)
虚拟文件系统(VFS)吧,使用套接字接口的时候,也是要分配一个文件描述符,然后后续所有的I/O都通过这个文件描述符来操作(包括IO模型中要判断可读写状态)
五、命令
工具
stress 是一个 Linux 系统压力测试工具,可以模拟平均负载升高,io等待,线程多等场景
sysstat 包含了常用的 Linux 性能工具,用来监控和分析系统的性能
mpstat (Multiprocessor Statistics)是一个常用的多核 CPU 性能分析工具,用来实时查看每个 CPU 的性能指标
pidstat 是一个常用的进程性能分析工具,用来实时查看进程的 CPU、内存、I/O 以及上下文切换等性能指标。
pidstat -w 5(查看每个进程上下文切换)参数:cswch/s(自愿切换) nvcswch/s(非自愿切换,时间片到)
vmstat 用来分析系统的内存使用情况
可以查看整体的上下文切换情况(每秒cs(context switch)上下文切换,in(interrupt,中断次数))
sysbench 是一个多线程的基准测试工具
perf 是 Linux2.6.31 以后内置的性能分析工具
ab(apache bench)是一个常用的 HTTP 服务性能测试工具,模拟请求的客户端,测试性能
dstat 是一个新的性能工具,它吸收了 vmstat、iostat、ifstat 等几种工具的优点,可以同时观察系统的 CPU、磁盘 I/O、网络以及内存使用情况
strace 正是最常用的跟踪进程系统调用的工具
///
cachestat 提供了整个操作系统缓存的读写命中情况。
cachetop 提供了每个进程的缓存命中情况。
pcstat 这个工具,来查看文件在内存中的缓存大小以及缓存比例
pcstat /bin/ls
stress --cpu 1 --timeout 600 (模拟一个 CPU 使用率 100%,600秒)
///
模拟过程
模拟CPU压力:stress --cpu 1 --timeout 600
观察负载变化:watch -d uptime
观察cpu使用率变化:mpstat -P ALL 5
查看是哪个进程导致:pidstat -u 5 1
模拟多线程切换:sysbench --threads=10 --max-time=300 threads run
观察上下文切换:vmstat 1
观察那个进程导致:pidstat -w -u 1
命令
uptime : 查看1,5,15分钟系统负载
watch -d uptime(uptime 查看平均负载的变化情况)
watch:可以帮你监测一个命令的运行结果,省得你一遍遍的手动运行。在Linux下,watch是周期性的执行下个程序,并全屏显示执行结果
-d,高亮变化
watch -d cat /proc/interrupts
pidstat -u 5 1(线程情况间隔 5 秒后输出一组数据,-w 参数表示输出进程切换指标,-u 参数则表示输出 CPU 使用指标)
pidstat -p 24344 指定pid未24344的进程
pidstat -d -p 4344 1 3(-d 展示 I/O 统计数据)
vmstat 5 (内存使用情况,整体情况)
top 显示了系统总体的 CPU 和内存使用情况,以及各个进程的资源使用情况。
us 用户空间占用CPU百分比
sy 内核空间占用CPU百分比
ni 用户进程空间内改变过优先级的进程占用CPU百分比
id 空闲CPU百分比
wa 等待输入输出的CPU时间百分比
hi 硬件中断
si 软件中断
st: 实时
ps 则只显示了每个进程的资源使用情况。
- 进程状态
D 不可中断 uninterruptible sleep (usually IO) Sleep),一般表示进程正在跟硬件交互,并且交互过程不允许被其他进程或中断打断
R 运行 runnable (on run queue)
S 中断 sleeping
T 停止 traced or stopped
Z 表示僵尸进程,也就是进程实际上已经结束了,但是父进程还没有回收它的资源
top
ps
六、其他
Linux 通过 /proc 虚拟文件系统,向用户空间提供了系统内部状态的信息
proc 文件系统。它是一种内核空间和用户空间进行通信的机制,可以用来查看内核的数据结构,或者用来动态修改内核的配置
proc 文件系统同时也是很多性能工具的最终数据来源
/proc/softirqs 提供了软中断的运行情况;
/proc/interrupts 提供了硬中断的运行情况。
/proc/stat提供的就是系统的 CPU 和任务统计信息
你只关注 CPU 的话,
cat /proc/stat | grep ^cpu