==============
== ACE BLOG ==
==============

Linux 系统性能监测

Linux 负载

In UNIX computing, the system load is a measure of the amount of computational work that a computer system performs. The load average represents the average system load over a period of time. It conventionally appears in the form of three numbers which represent the system load during the last one-, five-, and fifteen-minute periods.(wikipedia)

系统负载是对当前CPU工作量的度量,被定义为特定时间段内运行队列中的进程数量

一般看到的都是 平均负载 (Load average),一分钟的, 五分钟的,十五分钟的。也就是这个特定的时间段分钟是1,5,15 分钟,并且是平均后的值。

平均负载是指单位时间内,系统处于可运行状态不可中断状态的平均进程数,他和CPU使用率并没有直接的关系,直观上的理解就是单位时间内的活跃进程数。(程序 Sleep 过程中,并不占用 CPU)

CPU完全空闲的时候,平均负荷为0;当CPU工作量饱和的时候,平均负荷为1。(和 CPU 使用率没有关系)

1分钟,5分钟,15分钟的值可以用来大概估算负载是呈现上升或者下降的趋势,如果 1 分钟的比较高,15 分钟的比较低,说明负载正在上升,反之负载在降低。

通常这三个命令可以用来显示系统的负载信息,top, uptime, w

top

image-20230203011126694

top 常用操作

  • M: 根据驻留内存大小进行排序(shift+m)
  • P: 根据 CPU 使用百分比大小进行排序 (shft+p)
  • e: 切换展示单位
  • m: 切换显示内存信息;
  • t: 切换显示进程和 CPU 状态信息;
  • c: 切换显示命令名称和完整命令行;
  • l: 显示/隐藏 平均负载和启动时间
  • T: 根据时间或累计时间进行排序
  • q: 退出

推荐 htop 有更多的功能

uptime

image-20230203011146604

w

image-20230203011157641

vmstat 命令

vmstat 显示的指标全部都是操作系统级别的

vmstat [options] [delay [count]]

  • **options:**命令行参数,可选
    • -S, –unit character Switches outputs between 1000 (k), 1024 (K), 1000000 (m), or 1048576 (M) bytes. Note this does not change the swap (si/so) or block (bi/bo) fields.
  • **delay:**间隔多久统计一次数据,可选
  • **count:**统计一次,可选
  • 若只传了 delay,则统计次数是无限次,结束统计后会打印本次所有数据的平均值

image-20230203011217815

内容解释

procs: r: 正在运行或者等待运行的 process 数量

procs: b: 无法中断的 sleep 状态的 process 数量

memory: swpd 虚拟内存的使用量 (默认单位 K, 大写1024换算, 可以用 vmstat -S M 切换到 M 计算)

memory: free 闲置的内存量

memory: buff 用于缓冲作用的内存量

memory: cache 用于高速缓存作用的内存量

cache 是为了弥补高速设备和低速设备的速度差异增加的中间层,最终起到加快访问速度的作用。

buffer 的主要目的进行流量整形,把突发的大数量较小规模的 I/O 整理成平稳的小数量较大规模的 I/O,以减少实际的物理IO响应次数

比如下载数据,等网络实际下载固定大小块的数据后一次性写入硬盘,而不是每下载几KB就写硬盘,这个积攒的数据块临时存储在内存开辟的 buffer 区,这样既能提高性能也能优化硬盘寿命。

swap: si: = swap in 每秒从交换空间(磁盘)换入内存中, 磁盘-> 内存(站在内存角度是 in)

swap: so: =swap out 每秒从内存写出到交换空间的内存量, 内存-> 磁盘 (站在内存角度是 out)

推荐阅读 swap 相关:https://huoding.com/2012/11/08/198

io: bi blocks/s 每秒接受的块数量,相当于写磁盘操作,默认块大小是4024byte(4K)块设备是系统上所有的磁盘等其他设备(block 大小和当前设备的文件系统格式有关,一般是 4096 Bytes 4KB, 一个 block 表示一次 IO 的最小单位)

io:bo blocks/s 每秒发出的块数量,相当于读磁盘操作

查看块大小

stat 命令

stat -f / File: “/” ID: 51f0bdfeb044c785 Namelen: 255 Type: ext2/ext3 Block size: 4096 Fundamental block size: 4096 Blocks: Total: 30696921 Free: 14582334 Available: 13326348 Inodes: Total: 7768320 Free: 7542696

格式化文件系统时指定自定义的 block 大小 -b

mkfs.ext4 -b 2048 /dev/sdb1

system:in 每秒中断数,包括时钟中断。(system:in < system:cs 中断会产生非进程上下文切换)

system:cs 每秒上下文切换数。例如执行系统调用需要从用户态切换到内核态,需要上下文切换、CPU 执行多个线程,更换要执行的线程时要进行上下文切换。切换上下文操作较慢,如果有太多切换操作,CPU 全部浪费在这里,程序本身没有处理多少,所以这个值要控制在较低的数值比较好。

进程上下文切换次数较多的情况下,很容易导致 CPU 将大量的时间耗费在寄存器、内核栈、以及虚拟内存等资源的保存和恢复上,进而缩短了真正运行进程的时间造成 Load 高。

类比 CPU 是一个同时只能做一道菜的厨房,进程就是不同的菜品,每一种菜如果抄的过程中要切换去做另外一道菜,需要先把原来炒的菜倒出来,存放在一个地方,然后把要做的菜找出来倒进锅里,同时各种需要的调味品准备好,开始抄,如果同一个厨房不断的切换菜品,大量时间会浪费在切换的准备工作上。

众多 goroutine 自身切换是由 GO 运行时控制,这个控制是在用户进程中的对操作系统不可见的,自然不会产生系统的上下文切换,GO 运行时会控制真实线程的数量,一般是 CPU 数量个。只有真实线程被操作系统切换时才会发生上下文切换,如果每一个 CPU 核心一个线程,自然不会有上下文切换操作(不考虑用户程序做系统调用的情况)

cpu:us 用户进程执行占用CPU时间的百分比(non kernel code)

cpu:sy 系统进程执行占用CPU时间的百分比(kernel code)

cpu:id 空间状态占用CPU的时间百分比( Time spent idle. Prior to Linux 2.5.41, this includes IO-wait time)

cpu:wa IO 等待时间占用CPU时间的百分比,如果这个比较高,说明IO性能有隐患,或者系统都在登录IO操作(磁盘性能差IO操作太慢、磁盘性能本身没问题但是IO操作太多、IO死锁、等)

cpu:st: 虚拟机的虚拟 CPU 等待物理机的真实CPU 所消耗的时间占比,这个在虚拟机(大部分云服务器)环境有用。(Time stolen from a virtual machine. Prior to Linux 2.6.11, unknown. Steal time is the percentage of time a virtual CPU waits for a real CPU while the hypervisor is servicing another virtual processor)

st 如果很高,可能出现这些问题:

  • 虚拟机被分配到CPU资源不够虚拟机中程序消耗的,也就是要对虚拟机升级配置,物理机 CPU 资源够用。
  • 物理机超卖,并且多个虚拟机都在运行CPU较重的任务,争夺CPU使用权,虚拟机配置没问题,物理机CPU不够了。

典型情况

CPU 使用率很低,但是负载很高

等待磁盘、网络等 I/O 完成的进程过多,导致进程队列长度过大,但是 CPU 可以运行的进程(满足运行条件的)却很少,导致 CPU 使用率低,但是无法去完成任务。(前面介绍过负载并不是CPU使用率)

系统负载高,不代表 CPU 资源不足。Load 高只是代表需要运行的队列累计过多。但队列中的任务实际可能是耗 CPU 的,也可能是耗 IO 等。

负载不高,但是程序执行速度不快

如果机器的 CPU 本身就很差,但是整个系统就运行很少的程序,任务队列本身就没有太多任务堆积,负载不会太高,但是因为 CPU 计算比较慢,所以任务运行不会太快

想让程序运行更快的建议

计算机运行速度越慢的操作越少用,比如磁盘文件读写,网络请求,数据库操作等,利用常见的 buffer, cache 等方案加速操作或聚合后减少操作次数。

降低程序不必要的计算量,比如重复序列化同样的数据,计算量减少后自然会减少程序占用的 CPU 时间。

单机根据机器性能分配合适数量的线程并发,做到等待 IO 和切换在比较均衡的情况下,可以最大化利用率。偏 IO 操作的程序通过更多并发任务提高整体运行速度,多个任务上下文切换的消耗远比IO操作低。

偏向 CPU 操作的任务尽量降低并发数,减小上下文切换消耗的 CPU 时间。计算型任务本来单一任务就可以占用大量的 CPU 时间,如果并发处理,反而带来了更多的上下文切换消耗,并不会加速程序运行的速度。