Linux性能分析


1. cpupower

可以设置 CPU 为 performance 模式来提高性能。

  1. 查看 CPU 支持的模式。

    cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors
  2. 设置为 performance 模式。

    cpupower frequency-set -g performance

    CPU 优化建议使用 cpupower 设置 CPU Performance 模式

2. top

top - 12:20:32 up 18:33,  0 users,  load average: 0.00, 0.00, 0.00
Tasks:   9 total,   1 running,   8 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem : 16345516 total, 15938648 free,   273724 used,   133144 buff/cache
KiB Swap:  4194304 total,  4194304 free,        0 used. 15840516 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
    1 root      20   0    1744   1088   1016 S   0.0  0.0   0:00.00 init
    7 root      20   0    1764     76      0 S   0.0  0.0   0:00.00 init
    8 root      20   0    1764     92      0 S   0.0  0.0   0:00.05 init
    9 k         20   0   75332  11712   4500 S   0.0  0.1   0:02.33 zsh
   13 k         20   0   58876   5144   2092 S   0.0  0.0   0:00.00 zsh
   53 k         20   0   75612   6764   1332 S   0.0  0.0   0:00.00 zsh
   54 k         20   0   75596   5424      0 S   0.0  0.0   0:00.30 zsh
   56 k         20   0    4536   1000    884 S   0.0  0.0   0:00.94 gitstatusd-linu
   94 k         20   0   45728   3712   3228 R   0.0  0.0   0:00.00 top

执行命令 uptime 也能得到与命令 top 结果第一行一样的结果。命令 w 和命令 cat /proc/loadavg 也能得到类似的结果。

2.1 指标说明

A Guide to the Linux “Top” Command

2.1.1 系统时间、正常运行时间和用户会话

12:20:32 up 18:33, 0 users表示系统时间、正常运行时间和用户会话。

可以使用 who 命令来查看当前那些用户在线。

2.1.2 内存使用情况

KiB Mem : 16345516 total, 15938648 free,   273724 used,   133144 buff/cache
KiB Swap:  4194304 total,  4194304 free,        0 used. 15840516 avail Mem

KiB MemKiB Swap 后的 totalfree 以及 used 分别表示系统内存和交换区总大小、可用大小、已使用的大小。

avail Mem 表示不使用交换分区的情况下,可以分配给进程使用的大小。

buff/cache 系统使用的缓冲区和缓存的总和。

buff 表示内核缓冲区使用的内存,cache 表示页缓存和 slab 使用的内存。

可以通过 man free 命令来获取详细的说明。

What do the “buff/cache” and “avail mem” fields in top mean?

2.1.3 任务

Tasks:   9 total,   1 running,   8 sleeping,   0 stopped,   0 zombie

linux-process-states

图片来源:How to Make Sense of Linux System Stats in Top

在 Linux 中,进程可能处于以下状态:

  1. 可运行 (R,Runnable):处于这种状态的进程要么在 CPU 上执行,要么出现在运行队列中,准备执行。
  2. 可中断睡眠 (S, Interruptible sleep):处于此状态的进程正在等待事件完成。
  3. 不间断睡眠 (D, Uninterruptible sleep):在这种情况下,进程正在等待 I/O 操作完成。
  4. 已停止 (T, Stopped):这些进程已被作业控制信号(例如按 Ctrl+Z)停止或因为它们正在被跟踪。
  5. 僵尸(Z, Zombie):内核在内存中维护各种数据结构以跟踪进程。一个进程可能会创建多个子进程,并且它们可能会在父进程还在时退出。但是,必须保留这些数据结构,直到父进程获得子进程的状态。这种数据结构仍然存在的终止进程称为僵尸进程。

D 和 S 状态的进程显示为 sleeping ,T状态的进程显示为 stopped 。僵尸的数量显示为 zombie 值。

top 命令默认显示的是进程相关的信息,可以按 SHIFT + H 键切换到显示线程相关的信息。

2.1.4 CPU 使用率

%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st

top(1) — Linux manual page

CPU 使用率部分显示了用于各种任务的 CPU 时间百分比:

  1. us, user 是 CPU 在用户空间中执行进程所花费的时间(time running un-niced user processes)。
  2. sy, system 是运行内核空间进程所花费的时间。
  3. ni, nice 是使用手动设置的 nice 执行进程所花费的时间(time running niced user processes)。

    Linux 使用 nice 值来确定进程的优先级。具有高 nice 值的进程对其他进程更好,并获得低优先级。同样,具有较低 nice 的进程获得更高的优先级。可以手动更改默认的 nice 值。

  4. id, idle 是 CPU 保持空闲的时间。
  5. wa, IO-wait 是 CPU 等待 I/O 完成所花费的时间。
  6. hi, hardware interrupts 是处理硬件所花费的时间。
  7. si, software interrupts 是处理软件所花费的时间。
  8. st, stolen, time hypervisor 从这个 vm 窃取的时间 (time stolen from this vm by the hypervisor)。

    在虚拟化环境中,一部分 CPU 资源分配给每个虚拟机 (VM)。操作系统检测到它何时有工作要做,但它无法执行它们,因为 CPU 在某个其他 VM 上很忙。以这种方式损失的时间量是被窃取时间。

2.1.5 平均负载

load average: 0.00, 0.00, 0.00 表示一分钟、五分钟和十五分钟内的系统的平均负载。

在 Linux 上,负载是在任何给定时刻处于 R 和 D 状态的进程数。平均负载值提供了一个相对衡量 CPU 必须等待事情完成的时间。

平均负载的解释也可以通过命令 man uptime 获得:

System load averages is the average number of processes that are either in a runnable or uninterruptable state. A process in a runnable state is either using the CPU or waiting to use the CPU. A process in uninterruptable state is waiting for some I/O access, eg waiting for disk. The averages are taken over the three time intervals. Load averages are not normalized for the number of CPUs in a system, so a load average of 1 means a single CPU system is loaded all the time while on a 4 CPU system it means it was idle 75% of the time.

另外,平均负载是一个指数移动平均,意味着之前的负载平均值的一小部分被计入当前值。更多的细节:Examining Load Average

如何理解 Linux 系统负荷呢?

为便于理解,把 CPU 想象成一个大桥,桥上只有一根车道(相当于 CPU 只有一个核),所有的车辆都要从这根到通过。

  1. 系统负载为 0,表示车道上一个车都没有。
  2. 系统负载为 0.5, 表示车道上一半的路段有车。
  3. 系统负载为 1,表示车道上全是车,但是所有车都能正常顺利的通行。
  4. 系统负载为 1.7,大桥已经被占满了(100%),后面等着上桥的车辆为桥面车辆的70%。

在多核系统上,需要将负载平均值除以 CPU 内核数以获得类似的度量。

区分 CPU 使用率和平均负载

High CPU utilization but low load average

  • 平均负载是衡量一段时间内在内核运行队列中等待的任务数量。
  • CPU 利用率是衡量当前 CPU 繁忙程度的指标。

单个 CPU 线程在 1 分钟内保持 100% 的 CPU 使用率可以让 1分钟平均负载 加 1。具有超线程(8 个虚拟内核)的 4 核 CPU 保持 100% 的 CPU 使用率 1 分钟可以让 1分钟平均负载 加 8。

2.1.6 任务区

PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
  1 root      20   0    1744   1088   1016 S   0.0  0.0   0:00.00 init
  7 root      20   0    1764     76      0 S   0.0  0.0   0:00.00 init
  8 root      20   0    1764     92      0 S   0.0  0.0   0:00.05 init
  9 k         20   0   75332  11712   4500 S   0.0  0.1   0:02.33 zsh
 13 k         20   0   58876   5144   2092 S   0.0  0.0   0:00.00 zsh
 53 k         20   0   75612   6764   1332 S   0.0  0.0   0:00.00 zsh
 54 k         20   0   75596   5424      0 S   0.0  0.0   0:00.30 zsh
 56 k         20   0    4536   1000    884 S   0.0  0.0   0:00.94 gitstatusd-linu
 94 k         20   0   45728   3712   3228 R   0.0  0.0   0:00.00 top
  1. PID

    进程 ID,一个唯一的正整数,用于标识进程。

  2. USER

    启动进程的用户的 有效(effective) 用户名(映射到用户 ID)。Linux为进程分配一个 真实用户ID(real user ID) 和一个 有效用户ID(effective user ID);后者允许进程代表另一个用户进行操作。(例如,非 root 用户可以提升为 root 以安装软​​件包。)

  3. PR 和 NI

    NI 字段显示进程的 nice 值。PR 字段从内核的角度显示了进程的调度优先级。nice 值影响进程的优先级。

  4. VIRT、RES、SHR 和 %MEM

    这三个字段与进程的内存消耗有关。

    • VIRT 是进程消耗的内存总量。这包括程序代码、进程存储在内存中的数据以及已交换到磁盘的任何内存区域。
    • RES 是进程在 RAM 中消耗的内存,%MEM 表示该值占可用 RAM 总量的百分比。
    • SHR 是与其他进程共享的内存量。
  5. S

    一个进程可能处于不同的状态。此字段以单字母形式显示进程状态。

    D – 不间断睡眠,I – 空闲,R – 运行,S – 睡眠,T – 被作业控制信号停止,t – 在跟踪期间被调试器停止, Z – 僵尸。

  6. TIME+

    进程自启动以来使用的总 CPU 时间,精确到百分之一秒。

  7. COMMAND

    进程的名称。

2.1.7 Linux 内存类型

下面的内容意译自 top(1) — Linux manual page 中 Linux Memory Types 部分。

Linux 中有三种类型的内存,其中一种是可选的。

  1. 物理内存:一种有限的资源,代码和数据在执行或引用时必须驻留在其中。
  2. 交换文件(可选的):当物理内存不足时,可以存放修改后的(脏)内存并在以后检索的地方。
  3. 虚拟内存:一种几乎无限的资源,用于以下目标。
    1. 抽象,不受物理内存地址/限制。
    2. 隔离,每个进程在一个单独的地址空间。
    3. 共享,单个映射可以满足多个需求。
    4. 灵活性,为文件分配一个虚拟地址。

无论内存采用哪种形式,都作为内存页(page)管理(通常 4096 字节)。

每个内存页都被限制为下表中的一个象限中。物理内存和虚拟内存都可以包含这四个中的任何一个,而交换文件只能包含象限 1 和象限 3。象限 4 中的内存在修改后会作为进程自己的专用交换文件。

                           Private | Shared
                       1           |          2
  Anonymous  . stack               |
             . malloc()            |
             . brk()/sbrk()        | . POSIX shm*
             . mmap(PRIVATE, ANON) | . mmap(SHARED, ANON)
            -----------------------+----------------------
             . mmap(PRIVATE, fd)   | . mmap(SHARED, fd)
File-backed  . pgms/shared libs    |
                       3           |          4

下面是对 top 命令中一些字段的解释:

  1. %MEMRES 的值除以总物理内存。
  2. CODE:象限 3 中 pgms 的大小。
  3. DATA:整个象限 1 中的值加上象限 3 中显示 mmap 文件支持(File-backed)的内存页大小的和。
  4. RES:任何占用物理内存的东西。从 Linux-4.5 开始,是以下三个字段的总和:
    1. RSan:象限 1 中内存页的大小,包括象限 3 中之前修改过的内存页的大小。
    2. RSfd:象限 3 加上象限 4。
    3. RSsh:象限 2。
  5. RSlkRES 中不能被换出内存的部分(所有象限)。
  6. SHRRES 中排除象限 1 ,但包括象限 2 和象限 4 以及部分象限 3。
  7. SWAP:可能是除象限 4 外的其他象限中的任何内容。
  8. USEDRESSWAP 的和。
  9. VIRT:正在使用和/或保留的所有内容(所有象限)。

注意:虽然程序映像和共享库被认为是进程私有的,但在内核中被当做共享的(shared, SHR)。

2.2 关注指标

2.2.1 ussy

us 低 和 sy 高的情况一般有两种:

  1. 用户态的代码写的很好,都压缩成了系统调用。
  2. 用户态的代码写的很差,导致全是小的系统调佣。

2.2.2 wa

wa 高表示硬盘或者网络 I/O wait 高。

2.2.3 si

网络压测时,很有可能会出现单个 CPU 的 si 很高的情况。优化思路就是让 si 均衡到多个 CPU 上,方式有:

完整资料:Scaling in the Linux Networking Stack

  1. RSS(Receive Side Scaling)

    就是俗称的网卡多队列。需要网卡硬件支持。

    把不同的流分散的不同的网卡多列中,至于网卡队列由哪个cpu处理还需要绑定网卡队列中断与 CPU。

    队列应不超过机器上 CPU 物理核的数量。

    RECEIVE-SIDE SCALING (RSS)

    还有一种叫XPS(Transmit Packet Steering)的技术:根据当前处理软中断的cpu选择网卡发包队列,适合于多队列网卡。主要是为了避免 CPU 由 RX 队列的中断进入到 TX 队列的中断时发生切换,导致 CPU cache 失效损失性能。

  2. RPS(Receive Packet Steering)

    网卡多队列的软件实现。

    单队列网卡或者虚拟网卡,把该网卡上的数据流让多个 CPU 处理。

    RECEIVE PACKET STEERING (RPS)

    开启脚本:rps.sh

    在 RPS 之上优化的版本叫 RFS(Receive Flow Steering)。

    当流量需要传输到用户态处理时,用处理软中断的 CPU 去处理用户态的逻辑。主要是为了避免 CPU 由内核态进入到用户态的时候发生切换,导致 CPU cache 失效损失性能。

    RECEIVE FLOW STEERING (RFS)

    使用硬件加速版本的 RFS 叫 Accelerated RFS(Receive Flow Steering)。

    ACCELERATED RFS

  3. Kernel Bypass

    Kernel Bypass(内核旁路)是绕过Linux内核(TCPIP协议栈)的技术,不使用Linux内核子系统的功能,采用自己实现的相同功能的代码来处理,从用户空间直接访问和控制设备内存,避免数据从设备拷贝到内核,再从内核拷贝到用户空间。

    Kernel Bypass目前主流实现方案有:DPDK、SolarFlare。

其他资料:

  1. MYSQL数据库网卡软中断不平衡问题及解决方案
  2. RPS 和 RFS 网卡多队列性能调优实践
  3. Redis 高负载下的中断优化
  4. Linux RSS/RPS/RFS/XPS对比

3. nmon

3.1 关注指标

3.1.1 内核指标(k)

Kernel and Load Average ---------------------------------------------------------|
|Global-CPU-Stats---->     0.5% user      Load Average  CPU use since boottime   |
| /proc/stat line 1        0.0% user_nice  1 mins  0.00 Uptime Days Hours Mins   |
|100 ticks per second      0.5% system     5 mins  0.00 Uptime    0    17   15   |
|100%=1 CPUcoreThread   1195.6% idle      15 mins  0.00 Idle      0    17  939   |
|       1   RunQueue       0.0% iowait                  Uptime has overflowed    |
|       0   Blocked        0.0% irq                                              |
|    1731.3 Context        0.0% softirq                 12 CPU core threads      |
|           Switch         0.0% steal                                            |
|       0.5 Forks          0.0% guest                   Boot time 1635930655     |
|    1743.8 Interrupts     0.0% guest_nice              05:10 PM 03-Nov-2021     |

如果 Context Switch 比较高,可能代码中的 syscall 非常多,或者程序中线程非常多。

Interrupts 指标反应了中断的密集情况。

  1. 如果网络程序压测试,Context SwitchInterrupts 都非常高,说明网络发送的都是小包,没有批量发送(writev)。

4. nload

nload -u H 用于看网卡实时网速。

PageUpPageDown 切换网卡。

5. tcpflow

更方便的实时解析网络数据包。比如解析 HTTP 协议:sudo tcpflow -c -e http

6. ifconfig

6.1 关注指标

主要关注每个网络下的 RX errors 0 dropped 0 overruns 0 frame 0TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 这几个指标,判断网络是否出现丢包错误之类的。

7. netstat

7.1 关注指标

7.1.1 网络栈统计信息

想看内核网络栈的统计信息应用命令 netstat -s ,其他的方式会有比较大的负担。

统计信息中主要关注的有统计数据中关于重传的数据:netstat -s | grep -i retran

23919133 segments retransmitted
TCPLostRetransmit: 6168959
12901177 fast retransmits
4674395 retransmits in slow start
TCPSynRetrans: 3104

7.1.2 网卡 MTU 和统计信息

netstat -i
Kernel Interface table
Iface      MTU    RX-OK RX-ERR RX-DRP RX-OVR    TX-OK TX-ERR TX-DRP TX-OVR Flg
docker0   1500        0      0      0 0             0      0      0      0 BMU
enp4s0    1500 117099502      0  45104 0      109843615      0      0      0 BMRU
lo       65536   323529      0      0 0        323529      0      0      0 LRU

8. ss

8.1 关注指标

8.1.1 连接的统计信息

想看 TCP 各个状态的连接数量:ss -s

8.1.2 TCP 连接的 timer 信息

命令 ss -et 可以看 TCP 上 keepalive 相关的信息。

8.1.3 TCP 连接上流量控制和拥塞控制的信息

命令 ss -it 可以看 TCP 连接上流量控制和拥塞控制的信息。

9. strace

sudo strace -p $pid 查看某个进程的系统调用。

10. perf

sudo perf top 是 on-cpu 系统分析工具。

on-cpu 时间即进程获得 CPU 使用权的时间,同理 off-cpu 即进程失去cpu使用权时度过的时间。

更多资料:

  1. perf Examples
  2. Off-CPU Analysis

11. 其他工具

linux_observability_tools

linux_static_tools

linux_benchmarking_tools

linux_tuning_tools

linux_observability_sar

perf-tools_2016

bcc_tracing_tools

图片来源 Linux Performance

12. 查看指定进程使用的内存和有多少内存放在了 Swap 中

$ egrep '^(Swap|Size):' /proc/$pid/smaps
Size:                780 kB
Swap:                  0 kB
Size:                  8 kB
Swap:                  0 kB
Size:                 24 kB
Swap:                  0 kB
Size:                 80 kB
Swap:                  0 kB
Size:               3460 kB
Swap:                  0 kB
Size:                  8 kB
Swap:                  0 kB

其中 Size 表示进程使用的某块内存的大小,Swap 和 SwapPss 表示该内存被交换到 Swap 中的大小。

What does pss mean in /proc/pid/smaps


文章作者: Kiba Amor
版权声明: 本博客所有文章除特別声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 Kiba Amor !
  目录