Linux 性能优化的全景指南,都在这一篇里了,建议收藏~
来源:https://www.ctq6.cn/linux%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96/
Linux 性能优化
性能优化
性能指标
高并发和响应快对应着性能优化的两个核心指标:吞吐和延时
应用负载角度:直接影响了产品终端的用户体验 系统资源角度:资源使用率、饱和度等
选择指标评估应用程序和系统性能
为应用程序和系统设置性能目标
进行性能基准测试
性能分析定位瓶颈
性能监控和告警
到底应该怎么理解”平均负载”
平均负载多少时合理
CPU 密集型进程,大量 CPU 使用会导致平均负载升高,此时两者一致 I/O 密集型进程,等待 I/O 也会导致平均负载升高,此时 CPU 使用率并不一定高 大量等待 CPU 的进程调度会导致平均负载升高,此时 CPU 使用率也会比较高
CPU
CPU上下文切换(上)
按照任务类型,CPU 上下文切换分为:
进程上下文切换
线程上下文切换
中断上下文切换
进程上下文切换
Linux 进程按照等级权限将进程的运行空间分为内核空间和用户空间。从用户态向内核态转变时需要通过系统调用来完成。
一次系统调用过程其实进行了两次 CPU 上下文切换:
CPU 寄存器中用户态的指令位置先保存起来,CPU 寄存器更新为内核态指令的位置,跳转到内核态运行内核任务;
系统调用结束后,CPU 寄存器恢复原来保存的用户态数据,再切换到用户空间继续运行。
系统调用过程中并不会涉及虚拟内存等进程用户态资源,也不会切换进程。和传统意义上的进程上下文切换不同。因此系统调用通常称为特权模式切换。
进程是由内核管理和调度的,进程上下文切换只能发生在内核态。因此相比系统调用来说,在保存当前进程的内核状态和CPU寄存器之前,需要先把该进程的虚拟内存,栈保存下来。再加载新进程的内核态后,还要刷新进程的虚拟内存和用户栈。
进程只有在调度到CPU上运行时才需要切换上下文,有以下几种场景:CPU时间片轮流分配,系统资源不足导致进程挂起,进程通过sleep函数主动挂起,高优先级进程抢占时间片,硬件中断时CPU上的进程被挂起转而执行内核中的中断服务。
线程上下文切换
线程上下文切换分为两种:
前后线程同属于一个进程,切换时虚拟内存资源不变,只需要切换线程的私有数据,寄存器等;
前后线程属于不同进程,与进程上下文切换相同。
同进程的线程切换消耗资源较少,这也是多线程的优势。
中断上下文切换
中断上下文切换并不涉及到进程的用户态,因此中断上下文只包括内核态中断服务程序执行所必须的状态(CPU寄存器,内核堆栈,硬件中断参数等)。
中断处理优先级比进程高,所以中断上下文切换和进程上下文切换不会同时发生
CPU上下文切换(下)
通过 vmstat 可以查看系统总体的上下文切换情况
vmstat 5 #每隔5s输出一组数据
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 0 103388 145412 511056 0 0 18 60 1 1 2 1 96 0 0
0 0 0 103388 145412 511076 0 0 0 2 450 1176 1 1 99 0 0
0 0 0 103388 145412 511076 0 0 0 8 429 1135 1 1 98 0 0
0 0 0 103388 145412 511076 0 0 0 0 431 1132 1 1 98 0 0
0 0 0 103388 145412 511076 0 0 0 10 467 1195 1 1 98 0 0
1 0 0 103388 145412 511076 0 0 0 2 426 1139 1 0 99 0 0
4 0 0 95184 145412 511108 0 0 0 74 500 1228 4 1 94 0 0
0 0 0 103512 145416 511076 0 0 0 455 723 1573 12 3 83 2 0
cs (context switch) 每秒上下文切换次数
in (interrupt) 每秒中断次数
r (runnning or runnable)就绪队列的长度,正在运行和等待CPU的进程数
b (Blocked) 处于不可中断睡眠状态的进程数
要查看每个进程的详细情况,需要使用pidstat来查看每个进程上下文切换情况
pidstat -w 5
14时51分16秒 UID PID cswch/s nvcswch/s Command
14时51分21秒 0 1 0.80 0.00 systemd
14时51分21秒 0 6 1.40 0.00 ksoftirqd/0
14时51分21秒 0 9 32.67 0.00 rcu_sched
14时51分21秒 0 11 0.40 0.00 watchdog/0
14时51分21秒 0 32 0.20 0.00 khugepaged
14时51分21秒 0 271 0.20 0.00 jbd2/vda1-8
14时51分21秒 0 1332 0.20 0.00 argusagent
14时51分21秒 0 5265 10.02 0.00 AliSecGuard
14时51分21秒 0 7439 7.82 0.00 kworker/0:2
14时51分21秒 0 7906 0.20 0.00 pidstat
14时51分21秒 0 8346 0.20 0.00 sshd
14时51分21秒 0 20654 9.82 0.00 AliYunDun
14时51分21秒 0 25766 0.20 0.00 kworker/u2:1
14时51分21秒 0 28603 1.00 0.00 python3
cswch 每秒自愿上下文切换次数(进程无法获取所需资源导致的上下文切换)
nvcswch 每秒非自愿上下文切换次数(时间片轮流等系统强制调度)
vmstat 1 1 #新终端观察上下文切换情况
此时发现cs数据明显升高,同时观察其他指标:
r列:远超系统CPU个数,说明存在大量CPU竞争
us和sy列:sy列占比80%,说明CPU主要被内核占用
in列:中断次数明显上升,说明中断处理也是潜在问题
pidstat -w -u 1 #查看到底哪个进程导致的问题
从结果中看出是 sysbench 导致 CPU 使用率过高,但是 pidstat 输出的上下文次数加起来也并不多。分析 sysbench 模拟的是线程的切换,因此需要在 pidstat 后加 -t 参数查看线程指标。
watch -d cat /proc/interrupts
发现次数变化速度最快的是重调度中断(RES),该中断用来唤醒空闲状态的CPU来调度新的任务运行。分析还是因为过多任务的调度问题,和上下文切换分析一致。
某个应用的CPU使用率达到100%,怎么办?
Linux作为多任务操作系统,将CPU时间划分为很短的时间片,通过调度器轮流分配给各个任务使用。为了维护CPU时间,Linux通过事先定义的节拍率,触发时间中断,并使用全局变了jiffies记录开机以来的节拍数。时间中断发生一次该值+1.
CPU使用率,除了空闲时间以外的其他时间占总CPU时间的百分比。可以通过/proc/stat中的数据来计算出CPU使用率。因为/proc/stat时开机以来的节拍数累加值,计算出来的是开机以来的平均CPU使用率,一般意义不大。可以间隔取一段时间的两次值作差来计算该段时间内的平均CPU使用率。性能分析工具给出的都是间隔一段时间的平均CPU使用率,要注意间隔时间的设置。
CPU使用率可以通过top 或 ps来查看。分析进程的CPU问题可以通过perf,它以性能事件采样为基础,不仅可以分析系统的各种事件和内核性能,还可以用来分析指定应用程序的性能问题。
perf top / perf record / perf report (-g 开启调用关系的采样)
sudo docker run --name nginx -p 10000:80 -itd feisky/nginx
sudo docker run --name phpfpm -itd --network container:nginx feisky/php-fpm
ab -c 10 -n 100 http://XXX.XXX.XXX.XXX:10000/ #测试Nginx服务性能
发现此时每秒可承受请求给长少,此时将测试的请求数从100增加到10000。在另外一个终端运行top查看每个CPU的使用率。发现系统中几个php-fpm进程导致CPU使用率骤升。
接着用perf来分析具体是php-fpm中哪个函数导致该问题。
perf top -g -p XXXX #对某一个php-fpm进程进行分析
系统的CPU使用率很高,为什么找不到高CPU的应用?
sudo docker run --name nginx -p 10000:80 -itd feisky/nginx:sp
sudo docker run --name phpfpm -itd --network container:nginx feisky/php-fpm:sp
ab -c 100 -n 1000 http://XXX.XXX.XXX.XXX:10000/ #并发100个请求测试
进程不停的崩溃重启(如段错误/配置错误等),此时进程退出后可能又被监控系统重启; 短时进程导致,即其他应用内部通过 exec 调用的外面命令,这些命令一般只运行很短时间就结束,很难用top这种间隔较长的工具来发现
可以通过pstree来查找 stress 的父进程,找出调用关系。
pstree | grep stress
发现是php-fpm调用的该子进程,此时去查看源码可以看出每个请求都会调用一个stress命令来模拟I/O压力。之前top显示的结果是CPU使用率升高,是否真的是由该stress命令导致的,还需要继续分析。代码中给每个请求加了verbose=1的参数后可以查看stress命令的输出,在中断测试该命令结果显示stress命令运行时存在因权限问题导致的文件创建失败的bug。
此时依旧只是猜测,下一步继续通过perf工具来分析。性能报告显示确实时stress占用了大量的CPU,通过修复权限问题来优化解决即可。
系统中出现大量不可中断进程和僵尸进程怎么办?
进程状态
R Running/Runnable,表示进程在CPU的就绪队列中,正在运行或者等待运行;
D Disk Sleep,不可中断状态睡眠,一般表示进程正在跟硬件交互,并且交互过程中不允许被其他进程中断;
Z Zombie,僵尸进程,表示进程实际上已经结束,但是父进程还没有回收它的资源;
S Interruptible Sleep,可中断睡眠状态,表示进程因为等待某个事件而被系统挂起,当等待事件发生则会被唤醒并进入R状态;
I Idle,空闲状态,用在不可中断睡眠的内核线程上。该状态不会导致平均负载升高;
T Stop/Traced,表示进程处于暂停或跟踪状态(SIGSTOP/SIGCONT, GDB调试);
X Dead,进程已经消亡,不会在top/ps中看到。
对于不可中断状态,一般都是在很短时间内结束,可忽略。但是如果系统或硬件发生故障,进程可能会保持不可中断状态很久,甚至系统中出现大量不可中断状态,此时需注意是否出现了I/O性能问题。
僵尸进程一般多进程应用容易遇到,父进程来不及处理子进程状态时子进程就提前退出,此时子进程就变成了僵尸进程。大量的僵尸进程会用尽PID进程号,导致新进程无法建立。
磁盘O_DIRECT问题
sudo docker run --privileged --name=app -itd feisky/app:iowait
ps aux | grep '/app'
dstat 1 10 #间隔1秒输出10组数据
之前 Top 查看的处于 D 状态的进程号,用 pidstat -d -p XXX 展示进程的 I/O 统计数据。发现处于 D 状态的进程都没有任何读写操作。在用 pidstat -d 查看所有进程的 I/O统计数据,看到 app 进程在进行磁盘读操作,每秒读取 32MB 的数据。进程访问磁盘必须使用系统调用处于内核态,接下来重点就是找到app进程的系统调用。
sudo strace -p XXX #对app进程调用进行跟踪
perf record -d
和 perf report
进行分析,查看app进程调用栈。sys_read()
读取数据,并且从 new_sync_read
和 blkdev_direct_IO
看出进程时进行直接读操作,请求直接从磁盘读,没有通过缓存导致iowait升高。僵尸进程
CPU性能指标
CPU使用率
用户CPU使用率, 包括用户态(user)和低优先级用户态(nice). 该指标过高说明应用程序比较繁忙.
系统CPU使用率, CPU在内核态运行的时间百分比(不含中断). 该指标高说明内核比较繁忙.
等待I/O的CPU使用率, iowait, 该指标高说明系统与硬件设备I/O交互时间比较长.
软/硬中断CPU使用率, 该指标高说明系统中发生大量中断.
steal CPU / guest CPU, 表示虚拟机占用的CPU百分比.
平均负载
理想情况下平均负载等于逻辑CPU个数,表示每个CPU都被充分利用. 若大于则说明系统负载较重.
进程上下文切换
包括无法获取资源的自愿切换和系统强制调度时的非自愿切换. 上下文切换本身是保证Linux正常运行的一项核心功能. 过多的切换则会将原本运行进程的CPU时间消耗在寄存器,内核占及虚拟内存等数据保存和恢复上
CPU缓存命中率
CPU缓存的复用情况,命中率越高性能越好. 其中L1/L2常用在单核,L3则用在多核中
性能工具
平均负载案例
先用uptime查看系统平均负载
判断负载在升高后再用mpstat和pidstat分别查看每个CPU和每个进程CPU使用情况.找出导致平均负载较高的进程.
上下文切换案例
先用vmstat查看系统上下文切换和中断次数
再用pidstat观察进程的自愿和非自愿上下文切换情况
最后通过pidstat观察线程的上下文切换情况
进程CPU使用率高案例
先用top查看系统和进程的CPU使用情况,定位到进程
再用perf top观察进程调用链,定位到具体函数
系统CPU使用率高案例
先用top查看系统和进程的CPU使用情况,top/pidstat都无法找到CPU使用率高的进程
重新审视top输出
从CPU使用率不高,但是处于Running状态的进程入手
perf record/report发现短时进程导致 (execsnoop工具)
不可中断和僵尸进程案例
先用top观察iowait升高,发现大量不可中断和僵尸进程
strace无法跟踪进程系统调用
perf分析调用链发现根源来自磁盘直接I/O
软中断案例
top观察系统软中断CPU使用率高
查看/proc/softirqs找到变化速率较快的几种软中断
sar命令发现是网络小包问题
tcpdump找出网络帧的类型和来源,确定SYN FLOOD攻击导致
根据不同的性能指标来找合适的工具:
CPU优化
应用程序优化
编译器优化:编译阶段开启优化选项,如gcc -O2
算法优化
异步处理:避免程序因为等待某个资源而一直阻塞,提升程序的并发处理能力。(将轮询替换为事件通知)
多线程代替多进程:减少上下文切换成本
善用缓存:加快程序处理速度
系统优化
CPU绑定:将进程绑定要1个/多个CPU上,提高CPU缓存命中率,减少CPU调度带来的上下文切换
CPU独占:CPU亲和性机制来分配进程
优先级调整:使用nice适当降低非核心应用的优先级
为进程设置资源显示: cgroups设置使用上限,防止由某个应用自身问题耗尽系统资源
NUMA优化: CPU尽可能访问本地内存
中断负载均衡: irpbalance,将中断处理过程自动负载均衡到各个CPU上
TPS、QPS、系统吞吐量的区别和理解
QPS(TPS)
并发数
响应时间
QPS(TPS)=并发数/平均相应时间
用户请求服务器
服务器内部处理
服务器返回给客户
QPS 类似 TPS,但是对于一个页面的访问形成一个 TPS,但是一次页面请求可能包含多次对服务器的请求,可能计入多次 QPSQPS(Queries Per Second)每秒查询率,一台服务器每秒能够响应的查询次数.
TPS(Transactions Per Second)每秒事务数,软件测试的结果.
系统吞吐量,包括几个重要参数:
内存
Linux内存是怎么工作的
内存映射
虚拟内存空间分布
用户空间内存从低到高是五种不同的内存段:
只读段 代码和常量等
数据段 全局变量等
堆 动态分配的内存,从低地址开始向上增长
文件映射 动态库、共享内存等,从高地址开始向下增长
栈 包括局部变量和函数调用的上下文等,栈的大小是固定的。一般8MB
内存分配与回收
分配
malloc 对应到系统调用上有两种实现方式:
brk() 针对小块内存(<128K),通过移动堆顶位置来分配。
内存释放后不立即归还内存,而是被缓存起来。
mmap()针对大块内存(>128K),直接用内存映射来分配,即在文件映射段找一块空闲内存分配。
前者的缓存可以减少缺页异常的发生,提高内存访问效率。但是由于内存没有归还系统,在内存工作繁忙时,频繁的内存分配/释放会造成内存碎片。
后者在释放时直接归还系统,所以每次mmap都会发生缺页异常。
在内存工作繁忙时,频繁内存分配会导致大量缺页异常,使内核管理负担增加。
回收
内存紧张时,系统通过以下方式来回收内存:
回收缓存:LRU算法回收最近最少使用的内存页面;
回收不常访问内存:把不常用的内存通过交换分区写入磁盘
杀死进程:OOM内核保护机制(进程消耗内存越大 oom_score 越大,占用 CPU 越多 oom_score 越小,可以通过 /proc 手动调整 oom_adj)
echo -16 > /proc/$(pidof XXX)/oom_adj
如何查看内存使用情况
free来查看整个系统的内存使用情况
top/ps来查看某个进程的内存使用情况
VIRT 进程的虚拟内存大小
RES 常驻内存的大小,即进程实际使用的物理内存大小,不包括swap和共享内存
SHR 共享内存大小,与其他进程共享的内存,加载的动态链接库以及程序代码段
%MEM 进程使用物理内存占系统总内存的百分比
怎样理解内存中的Buffer和Cache?
如何利用系统缓存优化程序的运行效率
缓存命中率
#首先安装Go
export GOPATH=~/go
export PATH=~/go/bin:$PATH
go get golang.org/x/sys/unix
go ge github.com/tobert/pcstat/pcstat
dd缓存加速
dd if=/dev/sda1 of=file bs=1M count=512 #生产一个512MB的临时文件
echo 3 > /proc/sys/vm/drop_caches #清理缓存
pcstat file #确定刚才生成文件不在系统缓存中,此时cached和percent都是0
cachetop 5
dd if=file of=/dev/null bs=1M #测试文件读取速度
#此时文件读取性能为30+MB/s,查看cachetop结果发现并不是所有的读都落在磁盘上,读缓存命中率只有50%。
dd if=file of=/dev/null bs=1M #重复上述读文件测试
#此时文件读取性能为4+GB/s,读缓存命中率为100%
pcstat file #查看文件file的缓存情况,100%全部缓存
O_DIRECT选项绕过系统缓存
cachetop 5
sudo docker run --privileged --name=app -itd feisky/app:io-direct
sudo docker logs app #确认案例启动成功
#实验结果表明每读32MB数据都要花0.9s,且cachetop输出中显示1024次缓存全部命中
strace -p $(pgrep app)
#strace 结果可以看到openat打开磁盘分区/dev/sdb1,传入参数为O_RDONLY|O_DIRECT
内存泄漏,如何定位和处理?
没正确回收分配的内存,导致了泄漏 访问的是已分配内存边界外的地址,导致程序异常退出
内存的分配与回收
虚拟内存分布从低到高分别是只读段,数据段,堆,内存映射段,栈五部分。其中会导致内存泄漏的是:
堆:由应用程序自己来分配和管理,除非程序退出这些堆内存不会被系统自动释放。
内存映射段:包括动态链接库和共享内存,其中共享内存由程序自动分配和管理
内存泄漏的危害比较大,这些忘记释放的内存,不仅应用程序自己不能访问,系统也不能把它们再次分配给其他应用。内存泄漏不断累积甚至会耗尽系统内存。
如何检测内存泄漏
预先安装systat,docker,bcc
sudo docker run --name=app -itd feisky/app:mem-leak
sudo docker logs app
vmstat 3
/usr/share/bcc/tools/memleak -a -p $(pidof app)
从 memleak 输出可以看到,应用在不停地分配内存,并且这些分配的地址并没有被回收。通过调用栈看到是 fibonacci 函数分配的内存没有释放。定位到源码后查看源码来修复增加内存释放函数即可。
为什么系统的 Swap 变高
缓存/缓冲区,属于可回收资源,在文件管理中通常叫做文件页 在应用程序中通过fsync将脏页同步到磁盘 交给系统,内核线程pdflush负责这些脏页的刷新 被应用程序修改过暂时没写入磁盘的数据(脏页),要先写入磁盘然后才能内存释放 内存映射获取的文件映射页,也可以被释放掉,下次访问时从文件重新读取
Swap原理
Swap本质就是把一块磁盘空间或者一个本地文件当作内存来使用,包括换入和换出两个过程:
换出:将进程暂时不用的内存数据存储到磁盘中,并释放这些内存
换入:进程再次访问内存时,将它们从磁盘读到内存中
Linux如何衡量内存资源是否紧张?
直接内存回收新的大块内存分配请求,但剩余内存不足。
此时系统会回收一部分内存;
kswapd0 内核线程定期回收内存。
为了衡量内存使用情况,定义了pages_min,pages_low,pages_high 三个阈值,并根据其来进行内存的回收操作。
剩余内存 < pages_min,进程可用内存耗尽了,只有内核才可以分配内存
pages_min < 剩余内存 < pages_low,内存压力较大,kswapd0执行内存回收,直到剩余内存 > pages_high
pages_low < 剩余内存 < pages_high,内存有一定压力,但可以满足新内存请求
剩余内存 > pages_high,说明剩余内存较多,无内存压力
pages_low = pages_min 5 / 4 pages_high = pages_min 3 / 2
NUMA 与 SWAP
numactl --hardware #查看处理器在Node的分布情况,以及每个Node的内存使用情况
0表示既可以从其他Node寻找空闲资源,也可以从本地回收内存
1,2,4 表示只回收本地内存,2表示可以会回脏数据回收内存,4表示可以用Swap方式回收内存。
swappiness
Swap升高时如何定位分析
free #首先通过free查看swap使用情况,若swap=0表示未配置Swap
#先创建并开启swap
fallocate -l 8G /mnt/swapfile
chmod 600 /mnt/swapfile
mkswap /mnt/swapfile
swapon /mnt/swapfile
free #再次执行free确保Swap配置成功
dd if=/dev/sda1 of=/dev/null bs=1G count=2048 #模拟大文件读取
sar -r -S 1 #查看内存各个指标变化 -r内存 -S swap
#根据结果可以看出,%memused在不断增长,剩余内存kbmemfress不断减少,缓冲区kbbuffers不断增大,由此可知剩余内存不断分配给了缓冲区
#一段时间之后,剩余内存很小,而缓冲区占用了大部分内存。此时Swap使用之间增大,缓冲区和剩余内存只在小范围波动
停下sar命令
cachetop5 #观察缓存
#可以看到dd进程读写只有50%的命中率,未命中数为4w+页,说明正式dd进程导致缓冲区使用升高
watch -d grep -A 15 ‘Normal’ /proc/zoneinfo #观察内存指标变化
#发现升级内存在一个小范围不停的波动,低于页低阈值时会突然增大到一个大于页高阈值的值
如何“快准狠”找到系统内存存在的问题
内存性能指标
系统内存指标 已用内存/剩余内存 共享内存 (tmpfs实现) 可用内存:包括剩余内存和可回收内存 缓存:磁盘读取文件的页缓存,slab分配器中的可回收部分 缓冲区:原始磁盘块的临时存储,缓存将要写入磁盘的数据
进程内存指标
虚拟内存:5大部分
常驻内存:进程实际使用的物理内存,不包括Swap和共享内存
共享内存:与其他进程共享的内存,以及动态链接库和程序的代码段
Swap 内存:通过Swap换出到磁盘的内存
可以直接从物理内存中分配,次缺页异常 需要磁盘 IO 介入(如 Swap),主缺页异常。此时内存访问会慢很多
内存性能工具
根据不同的性能指标来找合适的工具:
内存分析工具包含的性能指标:
如何迅速分析内存的性能瓶颈
通常先运行几个覆盖面比较大的性能工具,如 free,top,vmstat,pidstat 等
先用 free 和 top 查看系统整体内存使用情况
再用 vmstat 和 pidstat,查看一段时间的趋势,从而判断内存问题的类型
最后进行详细分析,比如内存分配分析,缓存/缓冲区分析,具体进程的内存使用分析等
常见的优化思路:
最好禁止 Swap,若必须开启则尽量降低 swappiness 的值
减少内存的动态分配,如可以用内存池,HugePage 等
尽量使用缓存和缓冲区来访问数据。如用堆栈明确声明内存空间来存储需要缓存的数据,或者用 Redis 外部缓存组件来优化数据的访问
cgroups 等方式来限制进程的内存使用情况,确保系统内存不被异常进程耗尽
/proc/pid/oom_adj 调整核心应用的 oom_score,保证即使内存紧张核心应用也不会被OOM杀死
vmstat 使用详解
vmstat 命令是最常见的 Linux/Unix 监控工具,可以展现给定时间间隔的服务器的状态值,包括服务器的 CPU 使用率,内存使用,虚拟内存交换情况,IO读写情况。可以看到整个机器的 CPU,内存,IO 的使用情况,而不是单单看到各个进程的 CPU 使用率和内存使用率(使用场景不一样)。
vmstat 2
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 0 1379064 282244 11537528 0 0 3 104 0 0 3 0 97 0 0
0 0 0 1372716 282244 11537544 0 0 0 24 4893 8947 1 0 98 0 0
0 0 0 1373404 282248 11537544 0 0 0 96 5105 9278 2 0 98 0 0
0 0 0 1374168 282248 11537556 0 0 0 0 5001 9208 1 0 99 0 0
0 0 0 1376948 282248 11537564 0 0 0 80 5176 9388 2 0 98 0 0
0 0 0 1379356 282256 11537580 0 0 0 202 5474 9519 2 0 98 0 0
1 0 0 1368376 282256 11543696 0 0 0 0 5894 8940 12 0 88 0 0
1 0 0 1371936 282256 11539240 0 0 0 10554 6176 9481 14 1 85 1 0
1 0 0 1366184 282260 11542292 0 0 0 7456 6102 9983 7 1 91 0 0
1 0 0 1353040 282260 11556176 0 0 0 16924 7233 9578 18 1 80 1 0
0 0 0 1359432 282260 11549124 0 0 0 12576 5495 9271 7 0 92 1 0
0 0 0 1361744 282264 11549132 0 0 0 58 8606 15079 4 2 95 0 0
1 0 0 1367120 282264 11549140 0 0 0 2 5716 9205 8 0 92 0 0
0 0 0 1346580 282264 11562644 0 0 0 70 6416 9944 12 0 88 0 0
0 0 0 1359164 282264 11550108 0 0 0 2922 4941 8969 3 0 97 0 0
1 0 0 1353992 282264 11557044 0 0 0 0 6023 8917 15 0 84 0 0
# 结果说明
- r 表示运行队列(就是说多少个进程真的分配到CPU),我测试的服务器目前CPU比较空闲,没什么程序在跑,当这个值超过了CPU数目,就会出现CPU瓶颈了。这个也和top的负载有关系,一般负载超过了3就比较高,超过了5就高,超过了10就不正常了,服务器的状态很危险。top的负载类似每秒的运行队列。如果运行队列过大,表示你的CPU很繁忙,一般会造成CPU使用率很高。
- b 表示阻塞的进程,这个不多说,进程阻塞,大家懂的。
- swpd 虚拟内存已使用的大小,如果大于0,表示你的机器物理内存不足了,如果不是程序内存泄露的原因,那么你该升级内存了或者把耗内存的任务迁移到其他机器。
- free 空闲的物理内存的大小,我的机器内存总共8G,剩余3415M。
- buff Linux/Unix系统是用来存储,目录里面有什么内容,权限等的缓存,我本机大概占用300多M
- cache cache直接用来记忆我们打开的文件,给文件做缓冲,我本机大概占用300多M(这里是Linux/Unix的聪明之处,把空闲的物理内存的一部分拿来做文件和目录的缓存,是为了提高 程序执行的性能,当程序使用内存时,buffer/cached会很快地被使用。)
- si 每秒从磁盘读入虚拟内存的大小,如果这个值大于0,表示物理内存不够用或者内存泄露了,要查找耗内存进程解决掉。我的机器内存充裕,一切正常。
- so 每秒虚拟内存写入磁盘的大小,如果这个值大于0,同上。
- bi 块设备每秒接收的块数量,这里的块设备是指系统上所有的磁盘和其他块设备,默认块大小是1024byte,我本机上没什么IO操作,所以一直是0,但是我曾在处理拷贝大量数据(2-3T)的机器上看过可以达到140000/s,磁盘写入速度差不多140M每秒
- bo 块设备每秒发送的块数量,例如我们读取文件,bo就要大于0。bi和bo一般都要接近0,不然就是IO过于频繁,需要调整。
- in 每秒CPU的中断次数,包括时间中断
- cs 每秒上下文切换次数,例如我们调用系统函数,就要进行上下文切换,线程的切换,也要进程上下文切换,这个值要越小越好,太大了,要考虑调低线程或者进程的数目,例如在apache和nginx这种web服务器中,我们一般做性能测试时会进行几千并发甚至几万并发的测试,选择web服务器的进程可以由进程或者线程的峰值一直下调,压测,直到cs到一个比较小的值,这个进程和线程数就是比较合适的值了。系统调用也是,每次调用系统函数,我们的代码就会进入内核空间,导致上下文切换,这个是很耗资源,也要尽量避免频繁调用系统函数。上下文切换次数过多表示你的CPU大部分浪费在上下文切换,导致CPU干正经事的时间少了,CPU没有充分利用,是不可取的。
- us 用户CPU时间,我曾经在一个做加密解密很频繁的服务器上,可以看到us接近100,r运行队列达到80(机器在做压力测试,性能表现不佳)。
- sy 系统CPU时间,如果太高,表示系统调用时间长,例如是IO操作频繁。
- id 空闲CPU时间,一般来说,id + us + sy = 100,一般我认为id是空闲CPU使用率,us是用户CPU使用率,sy是系统CPU使用率。
- wt 等待IO CPU时间
pidstat 使用详解
pidstat 主要用于监控全部或指定进程占用系统资源的情况,如CPU,内存、设备IO、任务切换、线程等。
pidstat –d interval times 统计各个进程的IO使用情况 pidstat –u interval times 统计各个进程的CPU统计信息 pidstat –r interval times 统计各个进程的内存使用信息 pidstat -w interval times 统计各个进程的上下文切换 p PID 指定PID
1、统计 IO 使用情况
pidstat -d 1 10
03:02:02 PM UID PID kB_rd/s kB_wr/s kB_ccwr/s Command
03:02:03 PM 0 816 0.00 918.81 0.00 jbd2/vda1-8
03:02:03 PM 0 1007 0.00 3.96 0.00 AliYunDun
03:02:03 PM 997 7326 0.00 1904.95 918.81 java
03:02:03 PM 997 8539 0.00 3.96 0.00 java
03:02:03 PM 0 16066 0.00 35.64 0.00 cmagent
03:02:03 PM UID PID kB_rd/s kB_wr/s kB_ccwr/s Command
03:02:04 PM 0 816 0.00 1924.00 0.00 jbd2/vda1-8
03:02:04 PM 997 7326 0.00 11156.00 1888.00 java
03:02:04 PM 997 8539 0.00 4.00 0.00 java
UID
PID
kB_rd/s:每秒进程从磁盘读取的数据量 KB 单位 read from disk each second KB
kB_wr/s:每秒进程向磁盘写的数据量 KB 单位 write to disk each second KB
kB_ccwr/s:每秒进程向磁盘写入,但是被取消的数据量,This may occur when the task truncates some dirty pagecache.
iodelay:Block I/O delay,measured in clock ticks
Command:进程名 task name
2、统计 CPU 使用情况
# 统计CPU
pidstat -u 1 10
03:03:33 PM UID PID %usr %system %guest %CPU CPU Command
03:03:34 PM 0 2321 3.96 0.00 0.00 3.96 0 ansible
03:03:34 PM 0 7110 0.00 0.99 0.00 0.99 4 pidstat
03:03:34 PM 997 8539 0.99 0.00 0.00 0.99 5 java
03:03:34 PM 984 15517 0.99 0.00 0.00 0.99 5 java
03:03:34 PM 0 24406 0.99 0.00 0.00 0.99 5 java
03:03:34 PM 0 32158 3.96 0.00 0.00 3.96 2 ansible
UID
PID
%usr: 进程在用户空间占用 cpu 的百分比
%system: 进程在内核空间占用 CPU 百分比
%guest: 进程在虚拟机占用 CPU 百分比
%wait: 进程等待运行的百分比
%CPU: 进程占用 CPU 百分比
CPU: 处理进程的 CPU 编号
Command: 进程名
3、统计内存使用情况
# 统计内存
pidstat -r 1 10
Average: UID PID minflt/s majflt/s VSZ RSS %MEM Command
Average: 0 1 0.20 0.00 191256 3064 0.01 systemd
Average: 0 1007 1.30 0.00 143256 22720 0.07 AliYunDun
Average: 0 6642 0.10 0.00 6301904 107680 0.33 java
Average: 997 7326 10.89 0.00 13468904 8395848 26.04 java
Average: 0 7795 348.15 0.00 108376 1233 0.00 pidstat
Average: 997 8539 0.50 0.00 8242256 2062228 6.40 java
Average: 987 9518 0.20 0.00 6300944 1242924 3.85 java
Average: 0 10280 3.70 0.00 807372 8344 0.03 aliyun-service
Average: 984 15517 0.40 0.00 6386464 1464572 4.54 java
Average: 0 16066 236.46 0.00 2678332 71020 0.22 cmagent
Average: 995 20955 0.30 0.00 6312520 1408040 4.37 java
Average: 995 20956 0.20 0.00 6093764 1505028 4.67 java
Average: 0 23936 0.10 0.00 5302416 110804 0.34 java
Average: 0 24406 0.70 0.00 10211672 2361304 7.32 java
Average: 0 26870 1.40 0.00 1470212 36084 0.11 promtail
UID PID Minflt/s : 每秒次缺页错误次数 (minor page faults),虚拟内存地址映射成物理内存地址产生的 page fault 次数 Majflt/s : 每秒主缺页错误次数 (major page faults), 虚拟内存地址映射成物理内存地址时,相应 page 在 swap 中 VSZ virtual memory usage : 该进程使用的虚拟内存 KB 单位 RSS : 该进程使用的物理内存 KB 单位 %MEM : 内存使用率 Command : 该进程的命令 task name
4、查看具体进程使用情况
pidstat -T ALL -r -p 20955 1 10
03:12:16 PM UID PID minflt/s majflt/s VSZ RSS %MEM Command
03:12:17 PM 995 20955 0.00 0.00 6312520 1408040 4.37 java
03:12:16 PM UID PID minflt-nr majflt-nr Command
03:12:17 PM 995 20955 0 0 java
END
官方站点:www.linuxprobe.com
Linux命令大全:www.linuxcool.com
刘遄老师QQ:5604215
Linux技术交流群:2636170
(新群,火热加群中……)
想要学习Linux系统的读者可以点击"阅读原文"按钮来了解书籍《Linux就该这么学》,同时也非常适合专业的运维人员阅读,成为辅助您工作的高价值工具书!
微信扫码关注该文公众号作者