4.4.12. 系统性能优化指导

4.4.12.1. 概述

嵌入式 Linux 系统中,性能优化确保系统高效运行、满足实时性资源约束关键环节。嵌入式设备通常具有有限硬件资源(如 CPU、内存存储空间),因此需要通过软件优化充分发挥硬件潜力,提升系统整体性能。优化不仅能够提高系统响应速度吞吐量,还延长设备使用寿命,降低功耗。

性能问题产生原因分析

嵌入式 Linux 系统中,性能问题产生可能多种原因引起,以下性能优化问题产生原因总结:

CPU 性能问题产生原因

  1. 负载任务过多

    • 系统运行负载任务,导致 CPU 使用率接近 100%。例如,某些计算密集型任务(如数据处理、图像渲染)占用大量 CPU 时间。

    • 解决方法:优化关键任务代码,减少计算复杂度;使用多线程进程技术分散任务负载;调整进程优先级,确保关键任务优先运行。

  2. 上下文切换频繁

    • 系统存在大量线程进程,频繁切换导致 CPU 时间浪费上下文切换上,降低实际处理任务时间。

    • 解决方法:减少不必要线程进程数量;优化线程同步机制,减少竞争;使用无锁编程技术。

  3. 中断处理过多

    • 硬件中断频繁,导致 CPU 花费大量时间处理中断请求,影响正常任务执行。例如,网络设备磁盘设备中断过多。

    • 解决方法:优化硬件设备中断处理机制,如调整中断触发方式(电平触发边沿触发);使用中断合并技术减少中断频率。

内存性能问题产生原因

  1. 内存不足

    • 系统运行占用内存任务,导致物理内存耗尽,频繁使用 swap 空间,降低系统性能。

    • 解决方法:优化应用程序,减少不必要内存分配;使用内存技术管理动态内存;合理配置 swap 空间,避免过度依赖 swap;考虑更换大容量内存器件。

  2. 内存碎片

    • 频繁内存分配释放导致内存碎片化,影响大块内存分配效率。

    • 解决方法:使用大页内存( Huge Pages)减少页表开销;优化内存分配策略,尽量减少块内存分配。

  3. 缓存策略不合理

    • 内核缓存策略(如文件缓存、磁盘缓存)配置不合理,导致缓存命中率低,增加磁盘 I/O 操作。

    • 解决方法:调整内核缓存参数,如 vm.dirty_ratiovm.dirty_background_ratio;优化文件系统缓存策略。

  4. OOM(Out of Memory)问题

    • 系统内存不足时, OOM Killer 随机杀死进程,导致系统稳定。

    • 解决方法:合理配置 OOM Killer 的行为,如调整 vm.overcommit_memoryvm.overcommit_ratio 参数;监控内存使用情况,及时发现内存不足问题。

磁盘性能问题产生原因

  1. I/O 阻塞

    • 磁盘 I/O 操作频繁,导致系统等待 I/O 操作时间过长。例如,大量文件读写操作磁盘性能不足。

    • 解决方法:优化文件系统,选择适合嵌入式设备文件系统(如 F2FS、 JFFS2 );调整 I/O 调度算法(如 Deadline 或 CFQ);使用异步 I/O( AIO)技术减少阻塞。

  2. 文件系统碎片

    • 文件系统使用时间过长,导致文件碎片化,影响文件读写速度。

    • 解决方法:定期进行文件系统碎片整理;使用支持在线碎片整理文件系统。

  3. 磁盘性能不足

    • 磁盘设备性能不足,无法满足系统需求。例如,使用低速机械硬盘闪存设备。

    • 解决方法:升级磁盘设备,如使用 SSD 替代机械硬盘。

  4. 文件系统选择不当

    • 使用文件系统适合嵌入式设备使用场景,导致性能问题。例如,使用传统的 ext3 文件系统闪存设备可能导致频繁擦写操作,降低性能。

    • 解决方法:根据设备特点选择合适文件系统,如 F2FS 适用闪存设备, XFS 适用文件存储。

网络性能问题产生原因

  1. 网络带宽不足

    • 网络带宽有限,无法满足系统对网络数据传输需求。例如,高并发网络请求导致网络拥塞。

    • 解决方法:升级网络设备,如使用高带宽网卡交换机;优化网络拓扑结构,减少网络延迟。

  2. TCP 参数配置不合理

    • TCP 参数(如 tcp_max_syn_backlogtcp_tw_reuse)配置不合理,导致网络连接建立释放效率低下。

    • 解决方法:调整 TCP 参数,优化网络连接性能;使用 TCP 快速打开( TFO)技术减少连接建立时间。

  3. 网络连接过多

    • 系统存在大量关闭网络连接,导致系统资源耗尽。例如,僵尸连接占用大量端口资源。

    • 解决方法:调整系统最大文件句柄数(ulimit -n);优化应用程序,及时关闭无用网络连接。

  4. 中断处理问题

    • 网络设备中断处理不当,导致网络数据包丢失延迟增加。

    • 解决方法:优化网络设备中断处理机制,如调整中断触发方式;使用 RPS(接收队列缩放)和 RFS(接收转向)技术提高多核 CPU 的网络处理能力。

系统配置问题产生原因

  1. 内核配置不合理

    • 内核包含不必要模块功能,增加系统启动时间运行开销。

    • 解决方法:裁剪内核,移除不必要模块功能;根据实际需求定制内核配置。

  2. 系统服务过多

    • 系统运行不必要服务,占用系统资源,影响系统性能。

    • 解决方法:关闭不必要系统服务守护进程;优化系统服务启动顺序参数配置。

  3. 资源限制不合理

    • 系统资源限制(如内存限制、文件句柄限制)设置不合理,导致应用程序无法正常运行。

    • 解决方法:根据实际需求调整系统资源限制参数;监控资源使用情况,避免资源耗尽。

  4. 安全策略影响

    • 安全策略(如 SELinux、防火墙规则)过于严格,导致系统性能下降。例如,防火墙规则限制某些必要网络连接。

    • 解决方法:优化安全策略,确保影响正常业务;定期检查安全策略有效性,避免过度限制。

性能优化目标

  • 最大化硬件资源利用率。

  • 降低系统延迟,提高实时性。

  • 减少内存占用存储 I/O。

  • 优化网络性能,确保稳定通信。

性能优化层次

性能优化可以硬件、内核、应用系统优等多个层面进行。每个层面独特优化方法工具,以下优化层次结构:

  • 硬件优化:选择合适硬件合理配置硬件参数。

  • 内核优化:裁剪内核、调整内核参数、优化调度策略等。

  • 应用优化:优化应用程序代码、减少资源占用、提高并发性能。

  • 系统调优:调整系统服务、优化网络和 I/O 性能。

性能优化基本原则

  • 需求驱动:优化工作基于实际需求,明确性能瓶颈优化目标。

  • 最小化原则:在满足功能需求前提下,尽量减少系统资源占用。

  • 分阶段优化:按照硬件软件、从系统应用顺序逐步优化,避免盲目调整。

  • 测试验证:优化通过严格测试验证性能提升效果,确保系统稳定性。

4.4.12.2. 性能诊断工具

注意: 本章所述mpstatpidstatiostatsar 命令依赖于 sysstat 软件包。因此,用户使用这些命令之前需要在 Buildroot 中启用 sysstat 相关配置:

BR2_PACKAGE_SYSSTAT=y

然后,重新编译文件系统,关于 Buildroot 的详细内容可以参考本手册使用 Buildroot 制作文件系统 章节。

top

top 命令是 Linux 和类 Unix 系统广泛使用一个命令行工具,用于实时显示系统资源使用情况,包括 CPU 使用率、内存使用、运行进程等。它系统管理员提供一个动态实时视图,帮助他们监控系统性能,查找资源消耗进程以及进行性能调优。

top 的原理

top原理基于定期调用操作系统内核提供接口,收集系统资源使用情况统计数据,并这些数据动态展示用户。每当用户运行 top 命令时,它会执行以下操作:

  1. 内核接口调用top 使用 /proc 文件系统信息(如 /proc/stat/proc/meminfo/proc/loadavg/proc/[pid]/stat 等)来获取系统进程相关数据,如 CPU 的统计数据、上下文切换次数、中断次数等。

  2. 数据刷新top 默认每隔 3 秒刷新一次,以便提供实时系统资源使用情况。用户可以通过命令行参数调整刷新频率。

  3. 显示内容top 显示内容通常包括:

    • 系统信息:如系统负载、 CPU 使用率、内存使用、交换空间等。

    • 进程信息:包括每个进程的 PID、运行时间、 CPU 和内存使用率等。

/proc/stat/proc/loadavg 文件说明

/proc/stat 文件包含系统整体统计信息,涵盖了 CPU 使用情况、中断、上下文切换、进程信息多个方面。

root@buildroot:~# cat /proc/stat
cpu  62804 0 114380 58089226 5453 6389 8543 0 0 0
cpu0 4066 0 7342 7271002 241 1274 1875 0 0 0
cpu1 14258 0 32454 7237220 902 659 1076 0 0 0
cpu2 8234 0 14487 7260125 1136 785 1408 0 0 0
cpu3 5561 0 9637 7267498 1234 633 1122 0 0 0
cpu4 15888 0 25333 7242372 1002 652 1082 0 0 0
cpu5 725 0 615 7282803 546 636 406 0 0 0
cpu6 494 0 402 7284148 186 480 277 0 0 0
cpu7 13576 0 24107 7244055 202 1267 1294 0 0 0
intr 4026141 0 18137 644564 0 0 0 94726 0 0 0 0 0 0 2900948 0 0 0 0 4068 0 0 0 0 0 0 0 0 0 0 21199 0 0 42 0 133083 0 0 0 12288 123959 72875 0 0 0 8 4 157 22 0 0 61 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ctxt 5159099
btime 0
processes 3981
procs_running 1
procs_blocked 0
softirq 3450227 24 870373 5 151367 0 0 59 1249178 0 1179221

关键字说明

  1. CPU 使用情况

    • cpu

      • 含义:表示一行统计整个系统的 CPU 使用情况(所有 CPU 核心总和)。

    • 62804

      • 字段名:user

      • 含义:用户时间( User time)。表示 CPU 在用户态下运行时间(单位为 jiffies,一个 jiffy 通常是 1/100 秒,具体取决于系统的 HZ 值)。

      • 解释: CPU 在用户态下运行时间,即运行用户空间程序花费时间。

    • 0

      • 字段名:nice

      • 含义: nice 时间( Nice time)。表示 CPU 在用户态下运行 nice 优先级进程花费时间(单位为 jiffies)。

      • 解释: nice 优先级进程通常那些设置低优先级用户空间程序。在这个例子中,nice 时间为 0 ,表示没有 nice 优先级进程运行。

    • 114380

      • 字段名:system

      • 含义:内核时间( System time)。表示 CPU 在内核态下运行时间(单位为 jiffies)。

      • 解释: CPU 在内核态下运行时间,即执行内核代码花费时间,例如系统调用、中断处理等。

    • 58089226

      • 字段名:idle

      • 含义:空闲时间( Idle time)。表示 CPU 处于空闲状态时间(单位为 jiffies)。

      • 解释: CPU 没有执行任何任务时间。在这个例子中,空闲时间比较高,说明系统当前负载低。

    • 5453

      • 字段名:iowait

      • 含义: I/O 等待时间( I/O wait time)。表示 CPU 在等待 I/O 操作完成时所花费时间(单位为 jiffies)。

      • 解释: CPU 在等待磁盘 I/O 操作完成时间。如果这个值较高,可能表示系统存在 I/O 瓶颈。

    • 6389

      • 字段名:irq

      • 含义:中断时间( Interrupt time)。表示 CPU 处理硬件中断花费时间(单位为 jiffies)。

      • 解释: CPU 处理硬件中断时间,例如处理来自硬件设备中断信号。

    • 8543

      • 字段名:softirq

      • 含义:软中断时间( Softirq time)。表示 CPU 处理中断花费时间(单位为 jiffies)。

      • 解释:软中断内核软件层面模拟中断,用于处理一些内核任务,例如网络数据包处理、定时器事件等。

    • 0

      • 字段名:steal

      • 含义:被“窃取”的时间( Steal time)。在虚拟化环境中,表示 CPU 时间虚拟机监视器( Hypervisor)占用时间(单位为 jiffies)。

      • 解释:在虚拟化环境中,虚拟机可能需要等待物理 CPU 资源。steal 时间表示虚拟机等待物理 CPU 的时间。在这个例子中,steal 时间为 0 ,说明系统可能不是虚拟化环境,或者虚拟机没有等待 CPU 资源。

    • 0

      • 字段名:guest

      • 含义:运行虚拟机时间( Guest time)。表示 CPU 运行虚拟机花费时间(单位为 jiffies)。

      • 解释:在虚拟化环境中,guest 时间表示 CPU 运行虚拟机时间。在这个例子中,guest 时间为 0 ,说明系统可能不是虚拟化环境,或者没有运行虚拟机。

    • 0

      • 字段名:guest_nice

      • 含义:运行 nice 优先级虚拟机时间( Guest nice time)。表示 CPU 运行 nice 优先级虚拟机花费时间(单位为 jiffies)。

      • 解释:在虚拟化环境中,guest_nice 时间表示 CPU 运行 nice 优先级虚拟机时间。在这个例子中,guest_nice 时间为 0 ,说明系统可能不是虚拟化环境,或者没有运行 nice 优先级虚拟机。

  2. 中断统计

    • intr:中断统计信息。

      • 4026141:总中断次数。

      • 其他数字表示不同中断类型次数。

  3. 上下文切换

    • ctxt:上下文切换次数。5159099 表示系统已经执行了 5159099 次上下文切换。

  4. 系统启动时间

    • btime:系统启动时间(以单位)。0 表示系统启动时间从 1970 年 1 月 1 日开始计算(因为设备没有使能 RTC 时钟,系统每次启动是从 1970 零时启动)。

  5. 进程信息

    • processes:系统启动以来创建进程总数。3981 表示系统启动以来创建了 3981 个进程。

    • procs_running:当前运行进程数。1 表示当前有 1 个进程正在运行。

    • procs_blocked:当前处于不可中断睡眠状态进程数。0 表示没有进程处于不可中断睡眠状态。

  6. 中断统计

    • softirq:软中断统计信息。

      • 3450227:总软中断次数。

      • 其他数字表示不同类型中断次数。

/proc/loadavg 文件包含系统负载平均值,反映系统繁忙程度。以下提供日志内容详细说明:

root@buildroot:~# cat /proc/loadavg
0.00 0.02 0.00 1/199 3976

关键字说明

  1. 负载平均值

    • 0.00: 1 分钟平均负载。

    • 0.02: 5 分钟平均负载。

    • 0.00: 15 分钟平均负载。

  2. 进程信息

    • 1/199:当前运行进程数 / 总进程数。1 表示当前有 1 个进程正在运行,199 表示系统当前进程总数。

    • 3976:最后运行进程 ID。

CPU 利用率与 Load Average 的区别

top 显示系统信息中, CPU 的使用情况最为关键指标之一。为了更好理解这一数据,需要区分 CPU 利用率Load Average两个概念。它们虽然与 CPU 的使用情况密切相关,但反映角度含义有所不同。

CPU 利用率反映特定时间段内 CPU 的使用情况,显示 CPU 被占用百分比。如果 CPU 利用率长期过高,可能表明 CPU 超负荷运作,长期如此对系统造成损害。因此,保持合理的 CPU 利用率至关重要。需要注意是,使用自旋等待处理可能导致 CPU 利用率上升,此时 CPU 利用率不能准确反映 CPU 的真实负载。

  • CPU 时间 = user + system + nice + idle + iowait + irq + softirq

  • CPU 利用率 = 1 - (idle) / CPU 时间,用于测量当前系统的 CPU 负载。

  • CPU 用户利用率 = (user + nice) / CPU 时间,用于衡量用户程序对 CPU 的占用率。

  • CPU 内核利用率 = system / CPU 时间,反映程序对 Linux 内核系统调用占用的 CPU 时间。

  • I/O 利用率 = iowait / CPU 时间,衡量存储介质(如 FLASH、内存)的交互等待时间。

Load Average 则侧重于 CPU 的负载情况,它反映单位时间内,系统中有多少进程需要等待正在使用 CPU。 Load Average 并直接衡量 CPU 的使用百分比,而是关注 CPU 处理进程数量。当 Load Average 值过高时,说明系统有过进程争夺 CPU 资源,从而增加系统负担。理想情况下,一个 CPU 对应一个进程,但当 Load Average 除以逻辑 CPU 数大于 5 时,系统通常超负荷运行。

总结两者区别:

  • CPU 利用率:反映程序运行期间占用的 CPU 百分比。

  • CPU 负载:表示单位时间正在使用等待使用 CPU 的进程平均数。

top 的限制

尽管 top一个强大系统监控工具,但一些限制:

  1. 显示信息不够详细

    • top 默认展示内容虽然包含大部分关键信息,但某些特定资源信息深入分析可能需要额外命令参数。

    • 例如,网络活动、磁盘 I/O 等信息需要配合其他命令(如 iostatsar 等)一起使用。

  2. 实时性性能开销

    • 尽管 top一个实时工具,但每次刷新时会重新计算数据,这可能系统带来一定性能开销,尤其进程数目非常情况下。

    • 对于高频数据刷新,top性能可能有所下降。

  3. 定制较差

    • top 提供基本交互式操作参数设置,但对于复杂需求,可能需要进行较为繁琐配置。

    • 比如,某些高级视图、图形界面呈现、颜色配置等,需要命令行模式进行手动配置。

  4. 界面较为简陋

    • 一些现代监控工具,top界面显得比较简洁,不适合进行深度图形化分析。

    • 用户使用需要熟悉多种快捷键,以便动态界面有效切换获取信息。

  5. top 周期选定

    • CPU 的使用率受到周期影响,在 CPU 繁忙使用 top -d1top -d5结果差异非常的,周期越大,越接近实际平均负载。 考虑这样一种极端场景,在 1s 的时间内,前 100ms 负载 100%,后 900ms CPU 全部 idle,以 1s 为周期,负载就是 10%,以 100ms 为周期,负载出现了 100% 的情况,基于以上情况考虑,一般建议以 5s 作为 top周期 (top -d5)。

    • 需要特别注意是,top 命令适用长时间负载检测,对于一次性负载检查 (top -n1),top 实现第一次 top 计算周期是 200ms,以 200ms 周期计算出来的 CPU 使用率非常不准,会整体分析产生误导。

  6. CPU 使用率包含 iowait

    • 一般理解中 CPU 使用率指 CPU 忙占 CPU 总时间比值,处于 iowait 的线程实际占用 CPU,但是目前几乎所有统计工具中,都把 iowait 统计到 CPU 使用率中。

top 的参数说明

板端执行 top 命令后,执行 h 交互选项即可看到当前 top 命令支持所有功能,具体如下:

Help for Interactive Commands - procps-ng 3.3.17
Window 1:Def: Cumulative mode Off.  System: Delay 1.5 secs; Secure mode Off.

  Z,B,E,e   Global: 'Z' colors; 'B' bold; 'E'/'e' summary/task memory scale
  l,t,m,I   Toggle: 'l' load avg; 't' task/cpu; 'm' memory; 'I' Irix mode
  0,1,2,3,4 Toggle: '0' zeros; '1/2/3' cpu/numa views; '4' cpus two abreast
  f,F,X     Fields: 'f'/'F' add/remove/order/sort; 'X' increase fixed-width

  L,&,<,> . Locate: 'L'/'&' find/again; Move sort column: '<'/'>' left/right
  R,H,J,C . Toggle: 'R' Sort; 'H' Threads; 'J' Num justify; 'C' Coordinates
  c,i,S,j . Toggle: 'c' Cmd name/line; 'i' Idle; 'S' Time; 'j' Str justify
  x,y     . Toggle highlights: 'x' sort field; 'y' running tasks
  z,b     . Toggle: 'z' color/mono; 'b' bold/reverse (only if 'x' or 'y')
  u,U,o,O . Filter by: 'u'/'U' effective/any user; 'o'/'O' other criteria
  n,#, ^ O  . Set: 'n'/'#' max tasks displayed; Show: Ctrl+'O' other filter(s)
  V,v     . Toggle: 'V' forest view; 'v' hide/show forest view children

  k,r       Manipulate tasks: 'k' kill; 'r' renice
  d or s    Set update interval
  W,Y,!     Write config file 'W'; Inspect other output 'Y'; Combine Cpus '!'
  q         Quit
          ( commands shown with '.' require a visible task display window )
Press 'h' or '?' for help with Windows,
Type 'q' or <Esc> to continue

top 命令参数说明如下:

  • 常用选项

    • -d <秒数>:设置刷新间隔时间(单位秒),例如 top -d 2 表示每 2 秒刷新一次。

    • -n <次数>:指定 top 命令运行次数自动退出。

    • -p <进程 ID>:仅显示指定进程 ID 的信息。

    • -u <用户名>:仅显示指定用户名进程信息。

    • -b:以批处理模式运行,适用脚本调用。

    • -c:显示完整命令行截断。

  • 交互式命令(根据 help 菜单信息进行说明):

    • 全局命令:

      • Z:切换颜色显示。

      • B:切换粗体显示。

      • E/e:切换摘要 / 任务内存比例显示。

    • 切换显示项:

      • l:切换显示负载平均值。

      • t:切换显示任务 /CPU 信息。

      • m:切换显示内存信息。

      • I:切换 Irix 模式Solaris 模式。 Irix 模式:在 Irix 模式下, top 会显示进程累计 CPU 使用率,不考虑 CPU 核心数。如果一个进程系统使用多个核心,它的 CPU 使用率可能超过 100%。 Solaris 模式:在 Solaris 模式下, top 会进程的 CPU 使用率除以 CPU 核心数,从而显示每个进程平均 CPU 使用率。因此,一个进程的 CPU 使用率最多为 100%。

    • CPU 视图切换:

      • 0:切换显示零值。

      • 1/2/3:切换 CPU/NUMA 视图。

      • 4:切换 CPU 两列显示。

    • 设置:

      • f/F:添加 / 移除 / 排序 / 排序段。

      • X:增加固定宽度显示。

    • 查找定位:

      • L/&:查找 / 再次查找。

      • </>:左右移动序列。

    • 排序显示格式:

      • R:切换排序。

      • H:切换线程显示。

      • J:切换数字对齐。

      • C:切换坐标显示。

    • 其他切换:

      • c:切换命令名称 / 行显示。

      • i:切换空闲任务显示。

      • S:切换时间显示。

      • j:切换字符串对齐。

      • x:切换排序高亮。

      • y:切换运行任务高亮。

      • z:切换颜色 / 单色显示。

      • b:切换粗体 / 反向显示(仅xy有效)。

    • 过滤用户筛选:

      • u/U:按有效 / 任意用户过滤。

      • o/O:按其他标准过滤。

    • 显示设置:

      • n/#:设置显示最大任务数。

      • Ctrl+O:显示其他过滤条件。

      • V:切换森林视图。

      • v:隐藏 / 显示森林视图子项。

    • 进程管理:

      • k:终止进程(需要输入 PID)。

      • r:更改进程优先级(需要输入 PID 和的 nice 值)。

    • 更新时间间隔设置:

      • ds:更改刷新间隔时间。

    • 配置退出:

      • W:写入配置文件。

      • Y:检查其他输出。

      • !:合并 CPU。

      • q:退出 top

  • 管理器

    • f:进入管理器,允许选择显示哪些列。

    • o:设置当前排序规则。

top 的使用说明

  • 基本语法

    top [ 选项 ]
    

以下一个 top 命令输出示例:

top - 19:24:50 up 19:24,  2 users,  load average: 0.02, 0.02, 0.00
Tasks: 180 total,   1 running, 178 sleeping,   1 stopped,   0 zombie
%Cpu0  :   0.0/0.0     0[                                                 ]
%Cpu1  :   0.0/0.0     0[                                                 ]
%Cpu2  :   1.3/1.3     3[||                                               ]
%Cpu3  :   0.0/0.0     0[                                                 ]
%Cpu4  :   1.9/0.6     3[|                                                ]
%Cpu5  :   0.0/0.6     1[                                                 ]
%Cpu6  :   0.0/0.0     0[                                                 ]
%Cpu7  :   0.0/0.6     1[                                                 ]
GiB Mem : 67.5/1.3      [                                                 ]
GiB Swap:  0.0/0.0      [                                                 ]

  PID USER      PR  NI    VIRT    RES  %CPU  %MEM     TIME+ S COMMAND
    1 root      20   0    2.1m   0.1m   0.0   0.0   0:02.29 S init [3]
  237 root      20   0    5.8m   2.0m   0.0   0.2   0:00.23 S  `- /sbin/udevd -d
  404 dbus      20   0    3.3m   0.2m   0.0   0.0   0:00.00 S  `- dbus-daemon --system
  408 root      20   0    2.1m   0.1m   0.0   0.0   0:00.00 S  `- /usr/sbin/tee-supplicant -d /dev/teepriv0
  413 root      20   0    4.5m   0.2m   0.0   0.0   0:00.00 S  `- /usr/libexec/bluetooth/bluetoothd -n
  436 root      20   0   71.4m   0.6m   0.0   0.0   0:14.56 S  `- /usr/sbin/ntpd -g -p /var/run/ntpd.pid
  441 root      20   0    6.3m   1.9m   0.0   0.1   0:00.00 S  `- sshd: /usr/sbin/sshd [listener] 0 of 10-100 startups
...

输出内容解析如下:

  • 系统状态信息

    • top - 19:24:50 up 19:24,  2 users,  load average: 0.02, 0.02, 0.00

      • 当前时间: 19:24:50

      • 系统运行时间: 19 小时 24 分钟

      • 当前登录用户数: 2

      • 系统负载平均值: 0.02 ( 1 分钟)、 0.02 ( 5 分钟)、 0.00 ( 15 分钟)

  • 任务状态

    • Tasks: 180 total,   1 running, 178 sleeping,   1 stopped,   0 zombie

      • 进程数: 180

      • 运行进程数: 1

      • 睡眠进程数: 178

      • 停止进程数: 1

      • 僵尸进程数: 0

  • CPU 使用情况

    • %Cpu0  :   0.0/0.0     0[                                                 ]

      • CPU0 的使用率为 0.0%

    • %Cpu2  :   1.3/1.3     3[||                                               ]

      • CPU2 的使用率为 1.3%

    • %Cpu4  :   1.9/0.6     3[|                                                ]

      • CPU4 的使用率为 1.9%

  • 内存使用情况

    • GiB Mem : 67.5/1.3      [                                                 ]

      • 内存: 67.5 GiB

      • 使用内存: 1.3 GiB

  • 交换空间使用情况

    • GiB Swap:  0.0/0.0      [                                                 ]

      • 交换空间: 0.0 GiB

      • 使用交换空间: 0.0 GiB

  • 进程列表

    • PID:进程 ID

    • USER:进程所有者

    • PR:进程优先级

    • NI:进程的 nice 值

    • VIRT:进程占用虚拟内存

    • RES:进程占用物理内存

    • %CPU:进程占用的 CPU 百分比

    • %MEM:进程占用物理内存百分比

    • TIME+:进程累计运行时间

    • S:进程状态( S 表示睡眠, R 表示运行)

    • COMMAND:进程启动命令

htop 简介

当前系统集成htop 命令,htoptop 命令一个增强版本,提供更为丰富功能用户友好界面。与 top 相比,htop 支持图形化界面、使用更加直观,且支持交互功能,htop 具有下面特性:

  • CPU 使用率进程使用率采用 Solaris 模式(在 Solaris 模式下, top 会进程的 CPU 使用率除以 CPU 核心数,从而显示每个进程平均 CPU 使用率。因此,一个进程的 CPU 使用率最多为 100%)。

  • 支持在线进程设置 Nice、 CPU 亲和性进行修改。

root@buildroot:~# htop -h
htop 3.2.1
(C) 2004-2019 Hisham Muhammad. (C) 2020-2022 htop dev team.
Released under the GNU GPLv2+.

-C --no-color                   Use a monochrome color scheme
-d --delay=DELAY                Set the delay between updates, in tenths of seconds
-F --filter=FILTER              Show only the commands matching the given filter
-h --help                       Print this help screen
-H --highlight-changes[=DELAY]  Highlight new and old processes
-M --no-mouse                   Disable the mouse
-p --pid=PID[,PID,PID...]       Show only the given PIDs
   --readonly                   Disable all system and process changing features
-s --sort-key=COLUMN            Sort by COLUMN in list view (try --sort-key=help for a list)
-t --tree                       Show the tree view (can be combined with -s)
-u --user[=USERNAME]            Show only processes for a given user (or $USER)
-U --no-unicode                 Do not use unicode but plain ASCII
-V --version                    Print version info

Long options may be passed with a single dash.

Press F1 inside htop for online help.
See 'man htop' for more information.

启动后,htop 会以图形化界面显示 CPU、内存交换空间使用情况,并按 CPU 占用、内存占用进程进行排序。htop 启动通过 F1 显示详细帮助信息:

htop 3.2.1 - (C) 2004-2019 Hisham Muhammad. (C) 2020-2022 htop dev team.
Released under the GNU GPLv2+. See 'man' page for more info.

CPU usage bar: [low/normal/kernel/guest                  used%]
Memory bar:    [used/buffers/shared/cache                     used/total]
Swap bar:      [used/cache                                    used/total]

Type and layout of header meters are configurable in the setup screen.
In monochrome, meters display as different chars, in order: |#*@$%&.
Process state: R: running; S: sleeping; t: traced/stopped; Z: zombie; D: disk sleep

     Tab: switch to next screen tab        S-Tab: switch to previous screen tab
  Arrows: scroll process list              Space: tag process
  Digits: incremental PID search               c: tag process and its children
    F3 /: incremental name search              U: untag all processes
    F4 \: incremental name filtering        F9 k: kill process/tagged processes
    F5 t: tree view                         F7 ]: higher priority (root only)
       p: toggle program path               F8 [: lower priority (+ nice)
       m: toggle merged command                e: show process environment
       Z: pause/resume process updates         i: set IO priority
       u: show processes of a single user      l: list open files with lsof
       H: hide/show user process threads       x: list file locks of process
       K: hide/show kernel threads             s: trace syscalls with strace
       F: cursor follows process               w: wrap process command in multiple lines
   + - *: expand/collapse tree/toggle all F2 C S: setup
 N P M T: sort by PID, CPU%, MEM% or TIME F1 h ?: show this help screen
       I: invert sort order                F10 q: quit
  F6 > .: select sort column

Press any key to return.

以下帮助信息部分详细解释:

状态栏信息

  • CPU usage bar:显示不同 CPU 状态使用率,包括用户态( low)、 nice 用户态( normal)、系统态( kernel)、客户机虚拟 CPU( guest)。

  • Memory bar:显示物理内存使用情况,包括内存、缓冲区、共享内存、缓存。

  • Swap bar:显示交换分区使用情况,包括交换空间、缓存。

界面操作

  • Tab:切换一个屏幕标签页。

  • S-Tab:切换一个屏幕标签页。

  • Arrows:滚动进程列表。

  • Space:标记进程。

  • Digits:按 PID 增量搜索进程。

  • c:标记进程及其进程。

  • F3 /:按名称增量搜索进程。

  • U:取消标记所有进程。

  • F4 \:按名称过滤进程。

  • F9 k:杀死标记进程。

  • F5 t:以树状视图显示进程。

  • F7 ]:提高标记进程优先级(需要 root 权限)。

  • F8 [: 降低标记进程优先级(增加 nice 值)。

  • p:切换显示程序路径。

  • m:切换合并命令显示。

  • e:显示进程环境变量。

  • Z:暂停 / 恢复进程更新。

  • i:设置进程的 IO 优先级。

  • u:显示单个用户进程。

  • l:使用 lsof 列出进程打开文件。

  • H:隐藏 / 显示用户进程线程。

  • x:列出进程文件锁。

  • K:隐藏 / 显示内核线程。

  • s:使用 strace 跟踪系统调用。

  • F:光标跟随选中进程。

  • w:将进程命令换行显示。

  • + - *:展开 / 折叠树状视图切换所有。

  • F2 C S:进入设置屏幕。

  • N P M T:按 PID、 CPU%、 MEM% 或 TIME 排序。

  • F1 h ?:显示帮助屏幕。

  • I:反转排序顺序。

  • F10 q:退出 htop

  • F6 > .:选择序列。

进程状态

  • R:运行中。

  • S:休眠。

  • t:被跟踪 / 停止。

  • Z:僵尸进程。

  • D:等待 I/O。

其他

  • 标题栏显示类型布局可以设置屏幕配置。

  • 单色模式下,仪表显示不同字符,顺序为:|#*@$%&

mpstat

mpstat(Multiprocessor Statistics) 是一个用于报告每个可用 CPU 使用率统计信息工具,它sysstat一部分。mpstat 可以提供关于用户空间、系统空间、 I/O 等待时间、硬件中断的 CPU 时间百分比信息,对于性能分析系统监控非常有用。

mpstat 的原理

mpstat 通过读取 /proc/stat 文件数据收集 CPU 统计信息。/proc/stat一个虚拟文件,包含系统启动后 CPU 时间累积统计数据。mpstat 通过解析文件,计算不同 CPU 时间状态百分比,并展示用户。

mpstat 的参数说明

mpstat 命令行参数允许用户自定义输出格式内容。以下一些常用参数说明:

  • -A--all:显示所有 CPU 的统计信息。

  • -n--repeat:与 <interval><count> 一起使用,重复执行 mpstat 命令。

  • -T--threads:显示线程的 CPU 使用率。

  • -u--sum:只显示 CPU 总和统计信息。

  • -V--version:显示 mpstat版本信息。

  • -I {SUM|CPU|SCPU|ALL}:选择显示的 CPU 指标类型。

    • SUM:所有 CPU 指标总和。

    • CPU:每个 CPU 的指标。

    • SCPU:每个 CPU 的指标,不包括空闲 CPU。

    • ALL:所有 CPU 指标每个 CPU 的指标。

  • -N {<node_list>|ALL}:指定监控的 NUMA 节点。

  • --dec={ 0 | 1 | 2 }:设置固定小数点显示位数。

  • -o JSON:以 JSON 格式输出。

  • -P {<cpu_list>|ALL}:指定监控的 CPU 列表。

mpstat 的使用说明

mpstat 的命令格式如下:

格式:
   mpstat [options] [ <interval> [ <count> ] ]
            选项        时间间隔     采集次数

基本使用

用户可以通过简单mpstat 命令获取所有 CPU 的当前使用率统计信息。例如:

mpstat

显示所有 CPU 的使用率,包括用户空间(%usr)、系统空间(%sys)、 I/O 等待(%iowait)等。

重复执行

用户可以使用 -n 参数重复执行 mpstat 命令,以便监控 CPU 使用率时间变化。例如,每秒钟执行一次,共执行 5 次:

mpstat -n 1 5

显示特定 CPU

如果系统多个 CPU,用户可能只想查看特定 CPU 的统计信息。可以使用 -P 参数指定 CPU 列表:

mpstat -P 0,1

显示 CPU 0 和 CPU 1 的统计信息。

指定输出格式

用户可以通过 -o 参数选择输出格式,例如 JSON 格式:

mpstat -o JSON

mpstat 示例

以下一个 mpstat 命令示例输出:

Linux 6.1.83-DR-PL5.1_V1.0.16 (buildroot)       01/01/70        _aarch64_       (8 CPU)

05:05:39     CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
05:05:39     all    0.10    0.00    0.21    0.02    0.01    0.01    0.00    0.00    0.00   99.65

解释如下:

  • %usr:用户空间占用的 CPU 时间百分比( 0.10%)。

  • %nice:调整优先级进程占用的 CPU 时间百分比( 0.00%)。

  • %sys:系统空间占用的 CPU 时间百分比( 0.21%)。

  • %iowait:等待 I/O 操作完成时间百分比( 0.02%)。

  • %irq:处理硬件中断时间百分比( 0.01%)。

  • %soft:处理软件中断时间百分比( 0.01%)。

  • %steal:虚拟机其他虚拟机占用时间百分比( 0.00%)。

  • %guest:运行客户机虚拟 CPU 的时间百分比( 0.00%)。

  • %gnice:调整优先级客户机进程占用的 CPU 时间百分比( 0.00%)。

  • %idle: CPU 空闲时间百分比( 99.65%)。

pidstat

pidstatsysstat 工具集中一个命令,专门用于监控进程的 CPU、内存、线程、 I/O 及上下文切换系统资源占用情况。它提供一种手段用以更好理解优化系统性能。

pidstat 的原理

pidstat通过读取 /proc 文件系统相关文件收集进程性能数据。/proc 是 Linux 内核提供一个虚拟文件系统,包含系统进程实时信息。pidstat 分析这些数据,计算进程资源使用率,并用户友好方式展示。

pidstat 的参数说明

pidstat 支持多种参数,允许用户根据需要定制输出内容。以下一些常用参数详细说明:

  • -u:显示各个进程的 CPU 使用统计信息。

  • -r:显示各个进程内存使用情况。

  • -d:显示各个进程的 I/O 使用情况。

  • -w:显示各个进程上下文切换情况。

  • -t:显示线程信息。

  • -p <pid>:指定进程号,仅显示指定进程统计信息。

  • -l:显示命令所有参数。

  • -C <command>:仅显示命令包含匹配字符串进程。

  • -G <process_name>:显示符合匹配进程名字进程。

  • -T { TASK | CHILD | ALL }:显示任务线程或子进程信息。

  • --dec={ 0 | 1 | 2 }:设置固定小数点显示位数。

  • --human:以易读格式显示数值。

pidstat 的使用说明

pidstat 的命令格式如下:

格式:
   pidstat [options] [ <interval> [ <count> ] ]
            选项        时间间隔     采集次数

pidstat 示例

  • pidstat

    以下pidstat 命令示例输出:

    root@buildroot:~# pidstat
    Linux 6.1.83-DR-PL5.1_V1.0.16 (buildroot)       01/01/70        _aarch64_       (8 CPU)
    
    05:29:56      UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
    05:29:56        0         1    0.00    0.01    0.00    0.00    0.01     1  init [3]
    05:29:56        0         2    0.00    0.00    0.00    0.00    0.00     1  kthreadd
    05:29:56        0         9    0.00    0.00    0.00    0.00    0.00     3  kworker/u16:0+dsp_dump_wq
    05:29:56        0        11    0.00    0.00    0.00    0.00    0.00     0  ksoftirqd/0
    05:29:56        0        12    0.01    0.00    0.00    0.00    0.01     6  rcu_preempt
    ...
    
    • UID:进程所有者用户名。

    • PID:进程 ID。

    • %usr:用户空间占用的 CPU 时间百分比。

    • %system:系统空间占用的 CPU 时间百分比。

    • %guest:运行客户机虚拟 CPU 的时间百分比。

    • %wait:等待 I/O 操作完成时间百分比。

    • %CPU:进程占用总 CPU 时间百分比。

    • CPU:进程运行所在的 CPU。

    • Command:进程命令名称。

    注:运行 pidstat 不任何选项,统计信息系统启动开始各项统计信息

  • 使用-r 选项统计进程内存使用情况

    root@buildroot:~# pidstat -r 20 1
    Linux 6.1.83-DR-PL5.1_V1.0.16 (buildroot)       01/01/70        _aarch64_       (8 CPU)
    
    05:50:21      UID       PID  minflt/s  majflt/s     VSZ     RSS   %MEM  Command
    05:50:41        0      2042      0.05      0.00    3828    2724   0.20  pidstat
    
    Average:      UID       PID  minflt/s  majflt/s     VSZ     RSS   %MEM  Command
    Average:        0      2042      0.05      0.00    3828    2724   0.20  pidstat
    
    • minflt/s:从内存加载数据每秒出现次要错误数目,这些要求磁盘载入内存页面

    • majflt/s:从内存加载数据每秒出现主要错误数目,这些要求磁盘载入内存页面,一般内存使用紧张产生。

    • VSZ:占用虚拟内存大小,包括进入交换分区内存

    • RSS:占用物理内存大小,不包括进入交换分区内存

    • %MEM:进程使用物理内存百分比

  • 使用-d 选项统计进程 IO 使用情况

    root@buildroot:~# pidstat -d 20 1
    Linux 6.1.83-DR-PL5.1_V1.0.16 (buildroot)       01/01/70        _aarch64_       (8 CPU)
    
    05:57:00      UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s iodelay  Command
    05:57:20        0       799      0.00      0.20      0.00       0  syslogd
    
    Average:      UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s iodelay  Command
    Average:        0       799      0.00      0.20      0.00       0  syslogd
    
    • kB_rd/s:进程每秒磁盘读取数据量 ( 以 kB 为单位 )

    • kB_wr/s:进程每秒磁盘写入数据量 ( 以 kB 为单位 )

    • kB_ccwr/s:任务写入磁盘取消速率 ( 以 kB 为单位 )

    • iodelay:任务的 I/O 阻塞延迟,以时钟周期单位,包括等待同步块 I/O 和换入块 I/O 结束时间

  • 使用-w 选项显示进程上下文切换情况

    root@buildroot:~# pidstat -w 20 1
    Linux 6.1.83-DR-PL5.1_V1.0.16 (buildroot)       01/01/70        _aarch64_       (8 CPU)
    
    06:00:04      UID       PID   cswch/s nvcswch/s  Command
    06:00:24        0         1      0.20      0.00  init
    06:00:24        0         2      0.05      0.00  kthreadd
    06:00:24        0        11      0.05      0.00  ksoftirqd/0
    06:00:24        0        12      5.34      0.00  rcu_preempt
    06:00:24        0        13      1.00      0.00  migration/0
    06:00:24        0        17      1.00      0.00  migration/1
    ...
    
    Average:      UID       PID   cswch/s nvcswch/s  Command
    Average:        0         1      0.20      0.00  init
    Average:        0         2      0.05      0.00  kthreadd
    Average:        0        11      0.05      0.00  ksoftirqd/0
    Average:        0        12      5.34      0.00  rcu_preempt
    Average:        0        13      1.00      0.00  migration/0
    Average:        0        17      1.00      0.00  migration/1
    ...
    
    • cswch/s :表示每秒自愿上下文切换次数

    • nvcswch/s :表示每秒自愿上下文切换次数

    注:所谓自愿上下文切换,是进程无法获得资源导致上下文切换。而自愿上下文切换,则进程由于 cpu 分配时间耗尽,被系统强制调度导致上下文切换

iostat

iostat 命令是 Linux 系统用于分析 IO(输入 / 输出)性能常用工具,它属于 sysstat 软件包一部分,其名称为 “input/output statistics” 的缩写。它可以帮助用户了解系统磁盘和 CPU 的使用情况,从而对系统的 IO 性能进行评估优化。

iostat 的参数说明

  • -c:显示 CPU 使用情况。该选项输出 CPU 的利用率、用户时间、系统时间、空闲时间信息,帮助用户了解 CPU 的负载情况。

  • -d:显示磁盘使用情况。该选项输出磁盘读写次数、读写速率、平均队列长度、平均等待时间信息,帮助用户了解磁盘的 IO 性能。

  • --dec={0|1|2}:指定使用小数位数,默认为 2 位小数。例如,--dec=1 表示输出结果保留 1 位小数。

  • -g GROUP_NAME {DEVICE [...] | ALL}:显示一组设备统计信息。GROUP_NAME设备组名称,DEVICE组内设备名称,ALL 表示显示组内所有设备统计信息。

  • -H:此选项必须-g 选项一起使用,指示显示全局统计信息,而显示组中单个设备统计信息。

  • -h:以可读格式打印大小,例如字节单位转换易读的 KB、 MB 等单位。

  • -j {ID | LABEL | PATH | UUID | ...} [DEVICE [...] | ALL]:指定设备标识方式,可以设备 ID、标签、路径、 UUID 等。DEVICE具体设备名称,ALL 表示所有设备。

iostat 的使用说明

iostat 的命令格式如下:

格式:
   iostat [options] [ <device name> <interval> [ <count> ] ]
            选项        设备名称      时间间隔     采集次数
  • CPU 使用情况:当使用 -c 选项时,输出内容包括 %user(用户时间比)、%nice(低优先级用户时间比)、%system(系统时间比)、%iowait( IO 等待时间比)、%steal(虚拟化环境时间比)、%idle(空闲时间比)等指标。其中,%iowait 指标高时,可能表示系统存在磁盘 IO 瓶颈。

  • 磁盘使用情况:当使用 -d 选项时,输出内容包括 rrqm/s(每秒读取合并请求次数)、wrqm/s(每秒写入合并请求次数)、r/s(每秒读取次数)、w/s(每秒写入次数)、rkB/s(每秒读取的 KB 数)、wkB/s(每秒写入的 KB 数)、await(平均等待时间)、svctm(平均服务时间)、%util(磁盘利用率)等指标。其中,%util 指标接近 100% 时,可能表示磁盘处于饱和状态,存在 IO 瓶颈。

通过分析 iostat 命令输出结果,可以确定磁盘 IO 是否存在瓶颈。主要关注以下指标:

  • %iowait: CPU 等待 IO 操作时间比。如果该值高(例如超过 20%),可能表示磁盘 IO 性能不足,导致 CPU 等待时间过长。

  • %util:磁盘利用率。如果该值接近 100%,表示磁盘处于饱和状态,无法及时处理的 IO 请求。

  • await:平均等待时间。如果该值高,可能表示磁盘响应速度较慢,存在 IO 瓶颈。

  • svctm:平均服务时间。如果该值高,也可能表示磁盘性能较差,需要进一步分析。

iostat 示例

以下一个使用 iostat 命令示例:

root@buildroot:~# iostat -cd 1 5
Linux 6.1.83-DR-PL5.1_V1.0.16 (buildroot)       01/01/70        _aarch64_       (8 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.10    0.00    0.23    0.02    0.00   99.65

Device             tps    kB_read/s    kB_wrtn/s    kB_dscd/s    kB_read    kB_wrtn    kB_dscd
mmcblk0           0.54         4.71        47.18         0.00     106609    1067948          0
mmcblk0boot0      0.00         0.01         0.00         0.00        116          0          0
mmcblk0boot1      0.00         0.01         0.00         0.00        116          0          0
...

命令表示每 1 秒输出一次 CPU 和磁盘使用情况,共输出 5 次。通过观察输出结果,可以分析系统的 IO 性能状况,及时发现解决磁盘 IO 瓶颈问题,下面命令输出结果进行说明。

首先第一行:

Linux 6.1.83-DR-PL5.1_V1.0.16 (buildroot)       01/01/70        _aarch64_       (8 CPU)

Linux 6.1.83-DR-PL5.1_V1.0.16内核版本号,buildroot主机名字, 01/01/70 当前日期, _aarch64_ 是 CPU 的架构, (8 CPU) 显示当前系统的 CPU 的数量。

第二部分是 CPU 的相关信息,其实和 top 命令输出类似的。

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.10    0.00    0.23    0.02    0.00   99.65

cpu 属性说明:

  • %user: CPU 处在用户模式时间百分比。

  • %nice: CPU 处在带 NICE 值用户模式时间百分比。

  • %system: CPU 处在系统模式时间百分比。

  • %iowait: CPU 等待输入输出完成时间百分比。

  • %steal:管理程序维护一个虚拟处理器时,虚拟 CPU 的无意识等待时间百分比。

  • %idle: CPU 空闲时间百分比。

第三部分输出结果:

Device             tps    kB_read/s    kB_wrtn/s    kB_dscd/s    kB_read    kB_wrtn    kB_dscd
mmcblk0           0.54         4.71        47.18         0.00     106609    1067948          0
mmcblk0boot0      0.00         0.01         0.00         0.00        116          0          0
mmcblk0boot1      0.00         0.01         0.00         0.00        116          0          0

一列含义如下所示:

  • Device:/dev 目录磁盘(或分区)名称。

  • tps:该设备每秒传输次数。一次传输对应一次 I/O 请求,多个逻辑请求可能合并一次 I/O 请求。每次传输大小无法确定。

  • kB_read/s:每秒磁盘读取数据量,单位为 KB/s。

  • kB_wrtn/s:每秒写入磁盘数据量,单位为 KB/s。

  • kB_dscd/s:每秒磁盘丢失数据块数,单位为 KB/s。

  • kB_read:从磁盘读取数据量,单位为 KB。

  • kB_wrtn:写入磁盘数据量,单位为 KB。

  • kB_dscd:磁盘丢失数据块数。

需要注意是,当使用类似 iostat -dk 2命令时,每 2 秒钟收集一次数据。此时,kB_wrtn 表示在 2 秒写入磁盘数据量,kB_read 表示在 2 秒磁盘读取数据量,kB_dscd 表示在 2 秒磁盘丢失数据块数。

如果没有指定时间间隔参数,例如使用 iostat -dk,则 kB_wrtn 表示系统启动以来写入磁盘数据量,kB_read 表示系统启动以来磁盘读取数据量,kB_dscd 表示系统启动以来磁盘丢失数据块数。

除此以外,iostat 可以使用 -x 输出一些扩展列,例如下面输出:

Device            r/s     rkB/s   rrqm/s  %rrqm r_await rareq-sz     w/s     wkB/s   wrqm/s  %wrqm w_await wareq-sz     d/s     dkB/s   drqm/s  %drqm d_await dareq-sz     f/s f_await  aqu-sz  %util
mmcblk0          0.12      4.46     0.02  17.18    3.81    38.27    0.41     44.77     0.16  27.78   77.38   108.10    0.00      0.00     0.00   0.00    0.00     0.00    0.14    0.92    0.03   0.25
mmcblk0boot0     0.00      0.00     0.00   0.00    6.55     4.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.00   0.00
mmcblk0boot1     0.00      0.00     0.00   0.00    6.48     4.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00    0.00    0.00   0.00

扩展信息说明如下:

指标:

  • r/s:每秒磁盘发起操作次数。

  • rkB/s:每秒读取数据量,单位为 KB/s。

  • rrqm/s:每秒合并读取请求数。当系统调用读取数据时, VFS 将请求发送到文件系统,如果文件系统发现多个读取请求指向相同磁盘块,它会这些请求合并一个请求。

  • %rrqm:合并请求读取请求百分比。

  • r_await:每个操作平均响应时间,包含硬盘设备读取时间内核队列等待时间。

  • rareq-sz:平均请求大小。

指标:

  • w/s:每秒磁盘发起操作次数。

  • wkB/s:每秒写入数据量,单位为 KB/s。

  • wrqm/s:每秒合并请求数。

  • %wrqm:合并请求总写请求百分比。

  • w_await:每个操作平均响应时间,包含硬盘设备写入时间内核队列等待时间。

  • wareq-sz:平均请求大小。

抛弃指标:

  • d/s:每秒设备完成抛弃请求数(合并请求)。

  • dkB/s:每秒设备抛弃数据量,单位为 KB/s。

  • drqm/s:每秒排队设备合并抛弃请求数量。

  • %drqm:抛弃请求发送到设备之前合并百分比。

  • d_await:发出抛弃请求设备服务请求平均等待时间(以毫秒单位)。此指标包括请求队列等待时间以及设备处理请求时间。

  • dareq-sz:发送给设备抛弃请求平均大小(单位为 KB)。

其他指标:

  • aqu-sz:平均请求队列长度。

  • %util:设备一秒用于 I/O 操作时间百分比,即 I/O 消耗的 CPU 时间比例。该值反映设备带宽利用率。当串行服务请求设备此值接近 100% 时,通常表示设备已经饱和。对于支持并行请求设备(如 RAID 阵列现代 SSD),此值完全反映性能瓶颈。虽然的 %util 值表明 I/O 接近瓶颈,但意味着 I/O 没有瓶颈。通常,当 %util 超过 70% 时, I/O 压力较大。可以结合 vmstatb(等待资源进程数)和 wa( I/O 等待的 CPU 时间百分比,超过 30% 时表示 I/O 压力大)参数进一步分析。

iowait 指标解释常见误解

iowait 计算方法%iowait%idle子集,用于表示 CPU 处于空闲状态时,是否存在完成磁盘 I/O 请求。具体计算方法如下:

  • 如果 CPU 处于空闲状态(idle),内核检查:

    1. 是否本地磁盘 I/O 请求完成。

    2. 是否网络磁盘挂载操作。

  • 如果满足任一条件,iowait 计数器加 1 ;若满足,则 idle 计数器加 1 。

计算公式 :

iowait = (CPU 空闲时,等待 I/O 的时间 ) / (CPU 空闲的总时间 )

这个公式可以细化理解为:

  • 当 CPU 处于空闲状态( idle),操作系统检查是否有 I/O 请求完成。如果有 I/O 请求,系统标记为 iowait。

  • 如果在 CPU 空闲时,存在 I/O 请求正在等待完成,那么段时间计算为 iowait。

  • 如果没有 I/O 请求, CPU 空闲时间计算为 idle。

例如,假设间隔时间为 1 秒,总共有 100 个时钟周期:

  • sys 计数为 2

  • user 计数为 3

  • nice 计数为 0

  • iowait 计数为 1

  • steal 计数为 0

  • idle 计数为 94

这些计数百分比分别为:

  • sys: 2%

  • user: 3%

  • nice: 0%

  • iowait: 1%

  • steal: 0%

  • idle: 94%

iowait 的常见误解

  • 误解1:iowait 表示 CPU 等待 I/O 完成,在此期间无法处理其他任务

    实际上,iowait前提是 CPU 处于空闲状态,并且完成的 I/O 请求。虽然 iowait 表示 CPU 空闲,但意味着 CPU 不能接收其他任务。 CPU 空闲时,可能是因为没有运行任务,或者正在等待事件(例如磁盘 I/O、键盘输入网络数据)。

  • 误解2:iowait 高表示系统 I/O 瓶颈

    iowait意味着等待 I/O 的进程数量增加它们等待时间延长(进程由于等待 I/O 而休眠时间增加)。iowait 反映是 CPU 处于空闲状态有 I/O 请求完成,但直接意味着进程正在等待 I/O。

iowait不是单纯反映 I/O 瓶颈,它表示 CPU 空闲并且存在完成的 I/O 请求。iowait 增高并不一定表示 I/O 请求处理时间延长等待 I/O 的进程数量增加。理解一点有助于准确判断系统性能瓶颈。

可以借助下面图来理解:

iowait

可以看出, IO 没有发生任何变化,仅仅是 CPU 的空闲时间发生变化,iowait发生很大变化,因此根据 %iowait 不能判断出 IO 存在瓶颈。

vmstat

vmstat( Virtual Memory Statistics)是一个用于监控操作系统性能命令行工具,提供系统内存、进程、 I/O、 CPU 等方面统计信息。vmstat 收集展示数据来自内核不同子系统,比如内存管理、进程调度、 I/O 调度、虚拟内存等。操作系统内核周期性地更新这些统计数据,而 vmstat 通过查询内核提供这些数据显示系统实时状态。 vmstat优势在于其低开销特性,即使高负荷服务器上,也能够快速输出系统健康状态。然而,它无法单个进程进行深入分析,主要用于整个系统宏观监控。

vmstat 的原理

vmstat后台通过系统/proc 文件系统(尤其/proc/stat/proc/meminfo)访问系统实时性能数据,并周期显示统计结果。它基本原理如下:

  • 它会周期性地操作系统内核获取统计信息。

  • 这些信息基于操作系统内核调度、内存管理、 I/O 调度模块动态计算得出的。

  • vmstat 定期查询这些统计信息,并其以易读格式展示用户。

数据来源计算方式

  1. 内存统计

    内存统计数据内核管理,vmstat 主要关注物理内存使用情况,包括:

    • free:空闲内存

    • buff:用于缓冲内存

    • cache:用于文件缓存内存

    • swap:交换分区使用情况

    这些数据反映内存分配、释放、以及缓存交换空间使用情况。

  2. 进程与 CPU 统计

    • procs(进程状态):这部分显示进程系统状态,比如:

      • r:就绪队列进程

      • b:等待 I/O 的进程

      • w:进程睡眠等待 I/O 的数目

    • CPU 统计:包括 CPU 的使用情况:

      • us( user): 用户时间

      • sy( system): 系统时间

      • id( idle): 空闲时间

      • wa( wait): 等待 I/O 的时间

      • st( steal):虚拟化环境下,当前 CPU 时间其他虚拟机偷取时间

  3. I/O 统计

    • bi( blocks in):每秒从块设备读入

    • bo( blocks out):每秒写入设备

    • in( interrupts):每秒中断数量

    • cs( context switches):每秒上下文切换次数

  4. 交换空间

    • si( swap in):每秒交换空间读取数据量

    • so( swap out):每秒写入交换空间数据量

vmstat 的参数说明

vmstat 命令提供多种参数选项,用于定制输出内容格式。以下常用参数及其说明:

  • -a 显示活跃活跃内存统计信息。

  • -f 显示系统启动至今fork 数量。

  • -m 显示 slabinfo,即内核 slab 分配器详细信息。

  • -n开始显示一次字段名。

  • -S unit 指定输出单位,可选值k(千字节)、m(兆字节)。

  • -d 显示磁盘 I/O 统计信息。

  • -p disk partition 显示指定磁盘分区统计信息。

  • -V 显示 vmstat 版本信息。

  • delay 指定采样间隔时间(秒),用于周期性输出统计信息。

  • count 指定输出采样次数。

vmstat 的使用说明

vmstat 的命令格式如下:

格式:
   vmstat [options] [ <delay> [ <count> ] ]
            选项      时间间隔     采集次数

基本用法

  • 查看系统整体状态:运行 vmstat 命令,不带任何参数,将输出系统当前虚拟内存、进程、 CPU 等统计信息。

    vmstat
    
  • 周期性监控:通过指定 delaycount 参数,可以周期性地输出系统状态信息。例如,每 2 秒输出一次,共输出 5 次。

    vmstat 2 5
    

高级用法

  • 显示活跃活跃内存:使用 -a 参数,可以查看活跃活跃内存统计信息。

    vmstat -a
    
  • 显示磁盘 I/O 统计信息:使用 -d 参数,可以查看磁盘 I/O 操作详细统计。

    vmstat -d
    
  • 指定磁盘分区统计:通过 -p 参数,可以指定查看某个磁盘分区统计信息。

    vmstat -p /dev/sda1
    
  • 显示内核 slab 分配器信息:使用 -m 参数,可以查看内核 slab 分配器详细信息。

    vmstat -m
    

    注意: 在 X5 BSP 配置中,SLAB 默认开启,所以此项命令不可用。

  • 显示系统启动至今的 fork 数量:使用 -f 参数,可以查看系统启动至今fork 数量。

    vmstat -f
    

vmstat 示例

root@buildroot:~# vmstat
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 399916  27532 701884    0    0     1     5    7    9  0  0 100  0  0

vmstat 命令输出包含多个段,每个特定含义。以下一些常见输出及其说明:

  • procs:进程相关统计信息。

    • r:运行队列进程数。

    • b:处于不可中断睡眠状态进程数。

  • memory:内存相关统计信息。

    • swpd:已使用虚拟内存(交换空间)。

    • free:空闲内存。

    • buff:用作缓冲区内存量。

    • cache:用作页面缓存内存量。

  • swap:交换空间相关统计信息。

    • si:从交换空间读入内存速率。

    • so:写入交换空间速率。

  • io: I/O 操作相关统计信息。

    • bi:块设备读入速率。

    • bo:块设备写入速率。

  • system:系统相关统计信息。

    • in:每秒中断数。

    • cs:每秒上下文切换次数。

  • cpu: CPU 相关统计信息。

    • us:用户态 CPU 时间。

    • sy:系统态 CPU 时间。

    • id: CPU 空闲时间。

    • wa: CPU 等待 I/O 操作时间。

free

free一个用于显示系统内存使用情况命令行工具。它通过读取操作系统内存管理信息,提供关于物理内存( RAM)、交换空间( Swap)以及缓冲区缓存使用情况统计信息。free输出可以帮助用户快速了解系统内存使用状态,包括内存、已使用内存、空闲内存、共享内存、缓冲区缓存大小等。

free 的原理

free 命令主要以下系统文件获取信息:

  1. /proc/meminfo

    常见文件,free 命令读取内存使用情况数据来自文件。/proc/meminfo 包含系统内存详细统计信息,包括内存、已内存、空闲内存、缓存、交换空间信息。用户可以通过命令 cat /proc/meminfo 查看这些信息。

  2. /proc/swaps

    这个文件列出系统交换空间( swap)信息,包括每个交换设备文件使用情况。它显示交换分区总量、已使用量、空闲等,free 命令这个文件读取交换空间相关数据。

读取两个文件可以得到下面内容:

root@buildroot:~# cat /proc/meminfo
MemTotal:        1338740 kB
MemFree:          363632 kB
MemAvailable:     436000 kB
Buffers:           60960 kB
Cached:           688044 kB
SwapCached:            0 kB
Active:            68644 kB
Inactive:         691292 kB
Active(anon):        124 kB
Inactive(anon):   680432 kB
Active(file):      68520 kB
Inactive(file):    10860 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:             0 kB
SwapFree:              0 kB
Dirty:                 8 kB
Writeback:             0 kB
AnonPages:         11056 kB
Mapped:             5876 kB
Shmem:            669568 kB
KReclaimable:      15708 kB
Slab:              62424 kB
SReclaimable:      15708 kB
SUnreclaim:        46716 kB
KernelStack:        3264 kB
PageTables:         1060 kB
SecPageTables:         0 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:      669368 kB
Committed_AS:     828236 kB
VmallocTotal:   133143592960 kB
VmallocUsed:       30364 kB
VmallocChunk:          0 kB
Percpu:              864 kB
HardwareCorrupted:     0 kB
CmaTotal:         391168 kB
CmaFree:          287688 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
Hugetlb:               0 kB

root@buildroot:~# cat /proc/swaps
Filename                                Type            Size            Used            Priority

分别/proc/meminfo/proc/swaps内容进行说明。

/proc/meminfo 文件说明:

说明
MemTotal 1,338,740 kB 系统内存
MemFree 363,632 kB 空闲内存
MemAvailable 436,000 kB 可用内存(包括可回收缓存内存)。
这个数值考虑缓存缓冲区内存,它可以需要回收分配应用程序。
Buffers 60,960 kB 文件系统缓冲区使用内存
Cached 688,044 kB 文件系统缓存内存
SwapCached 0 kB 交换空间缓存内存,当前为 0 KB,意味着没有缓存交换空间。
Active 68,644 kB 活跃内存(正在使用内存)
Inactive 691,292 kB 活跃内存(暂时使用内存)
Active(anon) 124 kB 活跃匿名内存(无文件映射)
Inactive(anon) 680,432 kB 活跃匿名内存
Active(file) 68,520 kB 活跃文件内存(映射文件内存)
Inactive(file) 10,860 kB 活跃文件内存
Unevictable 0 kB 不能回收内存
Mlocked 0 kB 锁定内存(不允许交换磁盘)
SwapTotal 0 kB 交换空间总量(无交换空间)
SwapFree 0 kB 空闲交换空间(无交换空间)
Dirty 8 kB 修改尚未写回磁盘内存
Writeback 0 kB 正在写回磁盘内存
AnonPages 11,056 kB 匿名内存页(没有文件映射内存)
Mapped 5,876 kB 映射内存(映射文件设备内存)
Shmem 669,568 kB 共享内存
KReclaimable 15,708 kB 可回收内核内存
Slab 62,424 kB 内核用来管理数据结构内存
SReclaimable 15,708 kB 可回收的 slab 内存
SUnreclaim 46,716 kB 不可回收的 slab 内存
KernelStack 3,264 kB 内核内存
PageTables 1,060 kB 页表使用内存
SecPageTables 0 kB 安全页表使用内存
NFS_Unstable 0 kB NFS 不稳定内存
Bounce 0 kB 用于 bounce 缓存内存
WritebackTmp 0 kB 写回临时缓存内存
CommitLimit 669,368 kB 最大内存承诺
Committed_AS 828,236 kB 承诺内存量(包括交换磁盘部分)
VmallocTotal 133,143,592,960 kB 系统虚拟内存总量(大约 133 TB)
VmallocUsed 30,364 kB 使用虚拟内存
VmallocChunk 0 kB 可用虚拟内存连续大小
Percpu 864 kB 每个 CPU 的私有内存
HardwareCorrupted 0 kB 硬件损坏内存
CmaTotal 391,168 kB 连续内存( CMA)
CmaFree 287,688 kB 可用连续内存
HugePages_Total 0 系统页面总数(未启用页面)
HugePages_Free 0 可用页面
HugePages_Rsvd 0 预留页面
HugePages_Surp 0 超额分配页面
Hugepagesize 2,048 kB 每个页面大小
Hugetlb 0 kB 使用页面内存

/proc/swaps 文件说明如下:

说明
Filename 系统配置交换空间( Swap)
Type 交换空间
Size 0 kB 交换空间大小为 0 ,表示没有交换空间
Used 0 kB 当前没有交换空间使用
Priority 交换空间

日志中,swaps 相关输出显示为空,表明当前系统没有启用交换空间,这意味着系统没有任何交换设备(例如磁盘交换分区交换文件)。

free 的参数说明

执行 free --help 命令可以获取所有参数信息:

root@buildroot:~# free --help

Usage:
 free [options]

Options:
 -b, --bytes         show output in bytes
     --kilo          show output in kilobytes
     --mega          show output in megabytes
     --giga          show output in gigabytes
     --tera          show output in terabytes
     --peta          show output in petabytes
 -k, --kibi          show output in kibibytes
 -m, --mebi          show output in mebibytes
 -g, --gibi          show output in gibibytes
     --tebi          show output in tebibytes
     --pebi          show output in pebibytes
 -h, --human         show human-readable output
     --si            use powers of 1000 not 1024
 -l, --lohi          show detailed low and high memory statistics
 -t, --total         show total for RAM + swap
 -s N, --seconds N   repeat printing every N seconds
 -c N, --count N     repeat printing N times, then exit
 -w, --wide          wide output

     --help     display this help and exit
 -V, --version  output version information and exit

For more details see free(1).

各个参数说明如下:

  • -b,

    • --bytes:以字节单位显示内存使用情况。

    • --kilo:以千字节( KB)为单位显示内存使用情况。

    • --mega:以兆字节( MB)为单位显示内存使用情况。

    • --giga:以吉字节( GB)为单位显示内存使用情况。

    • --tera:以太字节( TB)为单位显示内存使用情况。

    • --peta:以字节( PB)为单位显示内存使用情况。

  • -k, --kibi:以千字节( KiB)为单位显示内存使用情况(基于 1024 )。

  • -m, --mebi:以兆字节( MiB)为单位显示内存使用情况(基于 1024 )。

  • -g, --gibi:以吉字节( GiB)为单位显示内存使用情况(基于 1024 )。

    • --tebi:以太字节( TiB)为单位显示内存使用情况(基于 1024 )。

    • --pebi:以字节( PiB)为单位显示内存使用情况(基于 1024 )。

  • -h,

    • --human:以易读格式显示内存使用情况(自动选择合适单位)。

    • --si:使用 1000 的不是 1024 的显示单位。

  • -l, --lohi:显示详细内存内存统计信息。

  • -t, --total:显示物理内存交换空间总和。

  • -s N, --seconds N:每隔 N 秒重复打印一次内存使用情况。

  • -c N, --count N:重复打印 N 次内存使用情况,然后退出。

  • -w,

    • --wide:使用输出格式,适合显示多列数据。

    • --help:显示帮助信息退出。

  • -V, --version:显示版本信息退出。

free 的使用说明

基本用法

  • 显示默认内存使用情况

    free
    

    默认情况下,free 以千字节( KB)为单位显示内存使用情况。

  • 易读格式显示内存使用情况

    free -h
    

    使用 -h 参数可以易读格式显示内存使用情况,自动选择合适单位(如 MiB、 GiB)。

  • 显示物理内存交换空间总和

    free -t
    

    使用 -t 参数可以显示物理内存交换空间总和。

高级用法

  • 以兆字节(MB)为单位显示内存使用情况

    free -m
    
  • 以吉字节(GB)为单位显示内存使用情况

    free -g
    
  • 每隔5秒重复打印一次内存使用情况,共打印3次

    free -s 5 -c 3
    
  • 显示详细内存内存统计信息

    free -l
    
  • 使用输出格式

    free -w
    

free 示例

易读格式显示内存使用情况:

root@buildroot:~# free -h
               total        used        free      shared  buff/cache   available
Mem:           1.3Gi       205Mi       355Mi       653Mi       746Mi       426Mi
Swap:             0B          0B          0B

输出解释如下:

  • Mem(物理内存)

    • total:系统物理内存大小。在这个例子中,总物理内存1.3Gi(约 1.3 吉字节)。

    • used:当前使用物理内存量。在这个例子中,已使用 205Mi(约 205 兆字节)。

    • free:当前完全空闲物理内存量。在这个例子中,空闲内存355Mi(约 355 兆字节)。

    • shared:被多个进程共享内存大小。在这个例子中,共享内存653Mi(约 653 兆字节)。

    • buff/cache:被用作系统缓冲区缓存内存量。在这个例子中,缓冲区缓存大小746Mi(约 746 兆字节)。

    • available:估算用于启动应用程序内存量,而无需交换其他应用程序内存。在这个例子中,可用内存426Mi(约 426 兆字节)。

  • Swap(交换空间)

    • total:系统交换空间大小。在这个例子中,总交换空间0B( 0 字节),表示系统没有配置交换空间。

    • used:当前使用交换空间量。在这个例子中,已使用交换空间0B( 0 字节)。

    • free:当前完全空闲交换空间量。在这个例子中,空闲交换空间0B( 0 字节)。

uptime

uptime 命令提供系统运行时间。除了系统运行时间,它可以获得系统其他详细信息,包括当前时间、运行会话用户数以及过去 1 、 5 和 15 分钟系统平均负载。

uptime 的原理

uptime一个用于显示系统运行时间当前负载平均值命令行工具。它通过读取 /proc/uptime/proc/loadavg 文件获取系统运行时间负载平均值。

  • /proc/uptime

    • 包含系统运行时间空闲时间统计信息。

    • 示例内容:

      4846.72 19364.37
      
      • 第一列(4846.72):系统运行时间(以单位)。

      • 第二列(19364.37):系统空闲时间(以单位)。

  • /proc/loadavg

    • 包含系统负载平均值。

    • 示例内容:

      0.05 0.03 0.00 1/199 3976
      
      • 三列分别表示 1 分钟、 5 分钟和 15 分钟负载平均值。

uptime 的参数说明

uptime 命令主要参数如下:

  • -p:以易读格式显示系统运行时间(如天、小时、分钟)。

  • -s:仅显示系统启动时间。

  • --help:显示帮助信息退出。

  • --version:显示版本信息退出。

uptime 的使用说明

基本用法

  • 显示系统运行时间负载平均值

    uptime
    

高级用法

  • 易读格式显示系统运行时间

    uptime -p
    
  • 显示系统启动时间

    uptime -s
    

uptime 示例

示例 1 :显示系统运行时间负载平均值

root@buildroot:~# uptime
20:54:32 up 20:54,  2 users,  load average: 0.05, 0.03, 0.00

解释如下:

  • 时间 (20:54:32): 当前系统时间为 20:54:32 。

  • 系统运行时间 (up 20:54): 系统已经运行了 20 分钟 54 秒。说明系统刚刚启动重启不久。

  • 用户数 (2 users): 当前有 2 个用户系统登录活跃。

  • 负载平均值 (load average: 0.05, 0.03, 0.00):

    • 第一个数字 (0.05): 过去 1 分钟负载平均值。负载低,表示系统没有过多计算任务。

    • 第二个数字 (0.03): 过去 5 分钟负载平均值。显示负载仍然低,表示系统段时间处于空闲状态。

    • 第三个数字 (0.00): 过去 15 分钟负载平均值。非常低,系统几乎处于空闲状态。

这个日志可以看出,系统运行时间短,负载平均值极低,说明系统当前非常空闲,没有处理多任务请求。

示例 2 :以易读格式显示系统运行时间

root@buildroot:~# uptime -p
up 20 hours, 54 minutes

示例 3 :仅显示系统启动时间

root@buildroot:~# uptime -s
2024-02-10 00:00:00

sar

sar ( System Activity Reporter ) 命令是 sysstat 软件包一部分,用于实时历史日志收集 Linux 系统各种元素性能统计数据。 Sar 提供 CPU 负载、内存分页、交换使用率、网络 I/O 等实时统计信息,它可以显示特定时间段历史数据。sar一个非常全面一个分析工具,可以称之为性能分析工具瑞士军刀。

sar 的原理

sar 通过读取 /proc 文件系统多个文件(如 /proc/uptime/proc/loadavg/proc/stat 等)来获取系统运行状态性能数据。sar特点能够连续对系统进行采样,获取大量性能数据,并这些数据保存文件中,便于后续分析。

sar 的参数说明

以下sar 命令常用参数及其说明:

  • -B:显示分页统计信息( Paging statistics)。

  • -b:显示 I/O 和传输速率统计信息( I/O and transfer rate statistics)。

  • -d:显示设备统计信息( Block devices statistics)。

  • -F [MOUNT]:显示文件系统统计信息( Filesystems statistics)。

  • -H:显示页面( Hugepages)使用情况统计信息( Hugepages utilization statistics)。

  • -I {<int_list> | SUM | ALL}:显示中断统计信息( Interrupts statistics)。

  • -m {<keyword> [,...] | ALL}:显示电源管理统计信息( Power management statistics)。

    • 关键字包括:

      • CPU: CPU 瞬时时钟频率。

      • FAN:风扇转速。

      • FREQ: CPU 平均时钟频率。

      • IN:电压输入。

      • TEMP:设备温度。

      • USB:连接系统的 USB 设备。

  • -n {<keyword> [,...] | ALL}:显示网络统计信息( Network statistics)。

    • 关键字包括:

      • DEV:网络接口。

      • EDEV:网络接口(错误)。

      • NFS: NFS 客户端。

      • NFSD: NFS 服务器。

      • SOCK:套接字( IPv4 )。

      • IP: IP 流量( IPv4 )。

      • EIP: IP 流量( IPv4 )(错误)。

      • ICMP: ICMP 流量( IPv4 )。

      • EICMP: ICMP 流量( IPv4 )(错误)。

      • TCP: TCP 流量( IPv4 )。

      • ETCP: TCP 流量( IPv4 )(错误)。

      • UDP: UDP 流量( IPv4 )。

      • SOCK6:套接字( IPv6 )。

      • IP6: IP 流量( IPv6 )。

      • EIP6: IP 流量( IPv6 )(错误)。

      • ICMP6: ICMP 流量( IPv6 )。

      • EICMP6: ICMP 流量( IPv6 )(错误)。

      • UDP6: UDP 流量( IPv6 )。

      • FC:光纤通道 HBA。

      • SOFT:基于软件网络处理。

  • -q [ <keyword> [,...] | PSI | ALL ]:显示系统负载压力停顿统计信息。

    • 关键字包括:

      • LOAD:队列长度负载平均值统计信息。

      • CPU:压力停顿 CPU 统计信息。

      • IO:压力停顿 I/O 统计信息。

      • MEM:压力停顿内存统计信息。

  • -r [ALL]:显示内存使用情况统计信息( Memory utilization statistics)。

  • -S:显示交换空间使用情况统计信息( Swap space utilization statistics)。

  • -u [ALL]:显示 CPU 使用情况统计信息( CPU utilization statistics)。

  • -v:显示内核统计信息( Kernel tables statistics)。

  • -W:显示交换统计信息( Swapping statistics)。

  • -w:显示任务创建系统切换统计信息( Task creation and system switching statistics)。

  • -y:显示 TTY 设备统计信息( TTY devices statistics)。

sar 的使用说明

使用语法

sar [options] [-A] [-o file] [ <interval> [ <count> ] ]

其中:

  • interval:为采样间隔;

  • count:为采样次数,默认值是 1 ;

  • -o file:表示命令结果二进制格式存放文件中, file 是文件名。

基本用法

  • 显示 CPU 使用情况统计信息

    sar -u 1 3
    

    每隔 1 秒统计一次,总共统计 3 次。

  • 显示内存使用情况统计信息

    sar -r 1 3
    

    每隔 1 秒统计一次,总共统计 3 次。

  • 显示设备统计信息

    sar -d 1 3
    

    每隔 1 秒统计一次,总共统计 3 次。

  • 显示网络接口统计信息

    sar -n DEV 1 3
    

    每隔 1 秒统计一次,总共统计 3 次。

高级用法

  • 统计结果保存文件

    sar -o test.txt -u 1 3
    

    将 CPU 使用情况统计结果二进制格式保存文件 test.txt 中。

  • 从文件读取统计结果

    sar -u -f test.txt
    

    从文件 test.txt读取 CPU 使用情况统计结果。

  • 显示所有统计信息

    sar -A 1 3
    

    每隔 1 秒统计一次,总共统计 3 次,显示所有类型统计信息。

sar 示例

示例 1 :显示 CPU 使用情况统计信息

root@buildroot:~# sar -u 1 3
Linux 6.1.83-DR-PL5.1_V1.0.16 (buildroot)       01/01/70        _aarch64_       (8 CPU)

23:44:36        CPU     %user     %nice   %system   %iowait    %steal     %idle
23:44:37        all      0.00      0.00      0.00      0.00      0.00    100.00
23:44:38        all      0.12      0.00      0.50      0.00      0.00     99.38
23:44:39        all      0.00      0.00      0.00      0.00      0.00    100.00
Average:        all      0.04      0.00      0.17      0.00      0.00     99.79

说明如下:

  1. 23:44:36

    • 含义:采样时间点。表示采样开始时间。

  2. CPU

    • 含义:表示一行统计信息对应的 CPU。all 表示统计所有 CPU 的综合情况。

  3. %user

    • 含义:用户态 CPU 使用率。表示 CPU 在用户态下运行时间时间百分比。

    • 示例

      • 23:44:370.00%,表示一秒内, CPU 在用户态下几乎没有运行。

      • 23:44:380.12%,表示一秒内, CPU 在用户态下运行了 0.12% 的时间。

  4. %nice

    • 含义: nice 优先级进程的 CPU 使用率。表示 CPU 在运行 nice 优先级进程时所占用时间百分比。

    • 示例

      • 23:44:370.00%,表示一秒内,没有 nice 优先级进程运行。

      • 23:44:380.00%,表示一秒内,没有 nice 优先级进程运行。

  5. %system

    • 含义:内核态 CPU 使用率。表示 CPU 在内核态下运行时间时间百分比。

    • 示例

      • 23:44:370.00%,表示一秒内, CPU 在内核态下几乎没有运行。

      • 23:44:380.50%,表示一秒内, CPU 在内核态下运行了 0.50% 的时间。

  6. %iowait

    • 含义: I/O 等待时间百分比。表示 CPU 在等待 I/O 操作完成时所占用时间百分比。

    • 示例

      • 23:44:370.00%,表示一秒内, CPU 没有等待 I/O 操作。

      • 23:44:380.00%,表示一秒内, CPU 没有等待 I/O 操作。

  7. %steal

    • 含义:被“窃取”的时间百分比。在虚拟化环境中,表示 CPU 时间虚拟机监视器( Hypervisor)占用时间百分比。

    • 示例

      • 23:44:370.00%,表示一秒内,没有 CPU 时间虚拟机监视器占用。

      • 23:44:380.00%,表示一秒内,没有 CPU 时间虚拟机监视器占用。

  8. %idle

    • 含义: CPU 空闲时间百分比。表示 CPU 处于空闲状态时间时间百分比。

    • 示例

      • 23:44:37100.00%,表示一秒内, CPU 完全处于空闲状态。

      • 23:44:3899.38%,表示一秒内, CPU 有 99.38% 的时间处于空闲状态。

  9. Average:

    • 含义:表示所有采样时间平均值。

    • 示例

      • %user0.04%,表示采样期间, CPU 在用户态下平均使用率为 0.04%。

      • %system0.17%,表示采样期间, CPU 在内核态下平均使用率为 0.17%。

      • %idle99.79%,表示采样期间, CPU 的平均空闲时间为 99.79%。

这个日志可以看出当前 CPU 使用情况:

  • 采样期间, CPU 的总体使用率非常低,大部分时间 CPU 处于空闲状态(%idle达 99.79%)。

  • 用户态(%user)和内核态(%system)的 CPU 使用率非常低,说明系统当前负载轻。

  • 没有 I/O 等待(%iowait 为 0%),也没有虚拟机监视器占用时间(%steal 为 0%),表明系统运行非常顺畅,没有明显性能瓶颈。


示例 2 :显示内存使用情况统计信息

root@buildroot:~# sar -r 1 3
Linux 6.1.83-DR-PL5.1_V1.0.16 (buildroot)       01/01/70        _aarch64_       (8 CPU)

23:45:14    kbmemfree   kbavail kbmemused  %memused kbbuffers  kbcached  kbcommit   %commit  kbactive   kbinact   kbdirty
23:45:15       357972    435880    163824     12.24     66128    688264    828364     61.88     73900    691580         4
23:45:16       357972    435880    163824     12.24     66128    688264    828364     61.88     73900    691580         4
23:45:17       357972    435880    163824     12.24     66128    688264    828364     61.88     73900    691580         8
Average:       357972    435880    163824     12.24     66128    688264    828364     61.88     73900    691580         5

说明如下

  1. 23:45:14

    • 含义:采样时间点。表示采样开始时间。

  2. kbmemfree

    • 含义:空闲物理内存量(以千字节单位)。

    • 示例

      • 23:45:15357972 KB,表示一秒内,系统有 357972 KB 的物理内存处于空闲状态。

  3. kbavail

    • 含义:可用物理内存量(以千字节单位)。包括空闲内存可以回收缓存 / 缓冲区内存。

    • 示例

      • 23:45:15435880 KB,表示一秒内,系统有 435880 KB 的物理内存可供使用。

  4. kbmemused

    • 含义:已使用物理内存量(以千字节单位)。

    • 示例

      • 23:45:15163824 KB,表示一秒内,系统有 163824 KB 的物理内存使用。

  5. %memused

    • 含义:物理内存使用率(百分比)。

    • 示例

      • 23:45:1512.24%,表示一秒内,系统有 12.24% 的物理内存使用。

  6. kbbuffers

    • 含义:用作缓冲区内存量(以千字节单位)。

    • 示例

      • 23:45:1566128 KB,表示一秒内,系统有 66128 KB 的内存用作缓冲区。

  7. kbcached

    • 含义:用作缓存内存量(以千字节单位)。

    • 示例

      • 23:45:15688264 KB,表示一秒内,系统有 688264 KB 的内存用作缓存。

  8. kbcommit

    • 含义:系统为了保证当前运行进程不会因为内存不足失败,所承诺最小内存量(以千字节单位)。

    • 示例

      • 23:45:15828364 KB,表示一秒内,系统承诺最小内存为 828364 KB。

  9. %commit

    • 含义:承诺内存内存(物理内存 + 交换空间)的比例(百分比)。

    • 示例

      • 23:45:1561.88%,表示一秒内,系统承诺内存内存的 61.88%。

  10. kbactive

    • 含义:活跃内存量(以千字节单位)。这些内存当前正在使用的,不太可能回收。

    • 示例

      • 23:45:1573900 KB,表示一秒内,系统有 73900 KB 的活跃内存。

  11. kbinact

    • 含义:不活跃内存量(以千字节单位)。这些内存当前使用的,可能回收用于其他用途。

    • 示例

      • 23:45:15691580 KB,表示一秒内,系统有 691580 KB 的活跃内存。

  12. kbdirty

    • 含义:脏内存量(以千字节单位)。这些内存包含尚未写入磁盘数据。

    • 示例

      • 23:45:154 KB,表示一秒内,系统有 4 KB 的内存。

  13. Average:

    • 含义:表示所有采样时间平均值。

    • 示例

      • kbmemfree357972 KB,表示采样期间,平均空闲物理内存为 357972 KB。

      • %memused12.24%,表示采样期间,物理内存平均使用率为 12.24%。

      • kbcommit828364 KB,表示采样期间,系统承诺最小内存为 828364 KB。

      • %commit61.88%,表示采样期间,承诺内存内存平均比例为 61.88%。

这个日志可以看出当前系统内存使用情况:

  • 系统物理内存使用率低(%memused 为 12.24%),表明系统当前内存负载轻。

  • 大部分内存用作缓存(kbcached 为 688264 KB)和缓冲区(kbbuffers 为 66128 KB),这有助于提高系统的 I/O 性能。

  • 系统承诺内存量(kbcommit)占内存比例高(%commit 为 61.88%),但实际使用内存量(kbmemused)仍然低,表明系统足够内存满足当前运行需求。

  • 活跃内存量(kbactive)较少,不活跃内存量(kbinact)较多,表明系统当前运行进程内存需求不高。


示例 3 :显示设备统计信息

root@buildroot:~# sar -d 1 3
Linux 6.1.83-DR-PL5.1_V1.0.16 (buildroot)       01/01/70        _aarch64_       (8 CPU)

23:46:11          DEV       tps     rkB/s     wkB/s     dkB/s   areq-sz    aqu-sz     await     %util
23:46:12      mmcblk0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
23:46:12    mmcblk0boot0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
23:46:12    mmcblk0boot1      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00

23:46:12          DEV       tps     rkB/s     wkB/s     dkB/s   areq-sz    aqu-sz     await     %util
23:46:13      mmcblk0      1.00      0.00      4.00      0.00      4.00      0.00      2.00      1.00
23:46:13    mmcblk0boot0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
23:46:13    mmcblk0boot1      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00

23:46:13          DEV       tps     rkB/s     wkB/s     dkB/s   areq-sz    aqu-sz     await     %util
23:46:14      mmcblk0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
23:46:14    mmcblk0boot0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
23:46:14    mmcblk0boot1      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00

Average:          DEV       tps     rkB/s     wkB/s     dkB/s   areq-sz    aqu-sz     await     %util
Average:      mmcblk0      0.33      0.00      1.33      0.00      4.00      0.00      2.00      0.33
Average:    mmcblk0boot0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
Average:    mmcblk0boot1      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00

说明如下

  1. 23:46:11

    • 含义:采样时间点。表示采样开始时间。

  2. DEV

    • 含义:磁盘设备名称。例如 mmcblk0mmcblk0boot0 等。

  3. tps

    • 含义:每秒传输的 I/O 操作次数( transactions per second)。表示每秒磁盘完成的 I/O 操作总数。

    • 示例

      • 23:46:13mmcblk0tps1.00,表示一秒内,mmcblk0 完成了 1 次 I/O 操作。

  4. rkB/s

    • 含义:每秒磁盘读取数据量(以千字节单位)。

    • 示例

      • 23:46:13mmcblk0rkB/s0.00,表示一秒内,mmcblk0 没有读取任何数据。

  5. wkB/s

    • 含义:每秒写入磁盘数据量(以千字节单位)。

    • 示例

      • 23:46:13mmcblk0wkB/s4.00,表示一秒内,mmcblk0 写入了 4 KB 的数据。

  6. dkB/s

    • 含义:每秒丢弃数据量(以千字节单位)。通常用于表示丢弃操作。

    • 示例

      • 23:46:13mmcblk0dkB/s0.00,表示一秒内,mmcblk0 没有丢弃任何数据。

  7. areq-sz

    • 含义:平均每次 I/O 操作数据量(以千字节单位)。

    • 示例

      • 23:46:13mmcblk0areq-sz4.00,表示一秒内,每次 I/O 操作平均数据量为 4 KB。

  8. aqu-sz

    • 含义:磁盘请求队列平均长度。

    • 示例

      • 23:46:13mmcblk0aqu-sz0.00,表示一秒内,磁盘请求队列平均长度为 0 。

  9. await

    • 含义:从请求 I/O 操作完成平均时间(以毫秒单位)。包括请求队列等待时间和 I/O 操作时间。

    • 示例

      • 23:46:13mmcblk0await2.00,表示一秒内, I/O 操作平均等待时间为 2 毫秒。

  10. %util

    • 含义:磁盘 I/O 操作占用 CPU 的时间百分比。表示磁盘采样期间利用率。

    • 示例

      • 23:46:13mmcblk0%util1.00,表示一秒内,mmcblk0利用率为 1%。

  11. Average:

    • 含义:表示所有采样时间平均值。

    • 示例

      • tps0.33,表示采样期间,mmcblk0平均 I/O 操作次数为 0.33 次 / 秒。

      • wkB/s1.33,表示采样期间,mmcblk0平均写入数据量为 1.33 KB/ 秒。

      • await2.00,表示采样期间,mmcblk0平均 I/O 等待时间为 2 毫秒。

      • %util0.33,表示采样期间,mmcblk0平均利用率为 0.33%。

这个日志可以看出当前系统磁盘 I/O 情况:

  • mmcblk0采样期间的 I/O 活动非常低。大部分时间没有 I/O 操作(tps 为 0 ),偶尔一些操作(wkB/s 为 4 KB)。

  • mmcblk0boot0mmcblk0boot1整个采样期间没有任何 I/O 活动。

  • 磁盘利用率(%util)非常低,表明磁盘没有成为系统性能瓶颈。

  • 平均每次 I/O 操作数据量(areq-sz)为 4 KB,表明 I/O 操作数据量小。

  • I/O 操作平均等待时间(await)为 2 毫秒,表明磁盘响应速度快。


示例 4 :显示网络接口统计信息

root@buildroot:~# sar -n DEV 1 3
Linux 6.1.83-DR-PL5.1_V1.0.16 (buildroot)       01/01/70        _aarch64_       (8 CPU)

23:46:45        IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s   %ifutil
23:46:46           lo      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
23:46:46         eth0      0.00      1.00      0.00      0.06      0.00      0.00      0.00      0.00
23:46:46        wlan0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
23:46:46        wlan1      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00

23:46:46        IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s   %ifutil
23:46:47           lo      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
23:46:47         eth0      2.00      4.00      0.12      0.79      0.00      0.00      0.00      0.00
23:46:47        wlan0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
23:46:47        wlan1      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00

23:46:47        IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s   %ifutil
23:46:48           lo      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
23:46:48         eth0      1.00      2.00      0.06      0.28      0.00      0.00      0.00      0.00
23:46:48        wlan0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
23:46:48        wlan1      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00

Average:        IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s   %ifutil
Average:           lo      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
Average:         eth0      1.00      2.33      0.06      0.38      0.00      0.00      0.00      0.00
Average:        wlan0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
Average:        wlan1      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00

说明如下

  1. 23:46:45

    • 含义:采样时间点。表示采样开始时间。

  2. IFACE

    • 含义:网络接口名称。例如 lo(本地回环接口)、eth0(以太网接口)、wlan0wlan1(无线网络接口)。

  3. rxpck/s

    • 含义:每秒接收数据包数量( received packets per second)。

    • 示例

      • 23:46:47eth0rxpck/s2.00,表示一秒内,eth0 接收了 2 个数据包。

  4. txpck/s

    • 含义:每秒发送数据包数量( transmitted packets per second)。

    • 示例

      • 23:46:47eth0txpck/s4.00,表示一秒内,eth0 发送了 4 个数据包。

  5. rxkB/s

    • 含义:每秒接收数据量(以千字节单位)。

    • 示例

      • 23:46:47eth0rxkB/s0.12,表示一秒内,eth0 接收了 0.12 KB 的数据。

  6. txkB/s

    • 含义:每秒发送数据量(以千字节单位)。

    • 示例

      • 23:46:47eth0txkB/s0.79,表示一秒内,eth0 发送了 0.79 KB 的数据。

  7. rxcmp/s

    • 含义:每秒接收压缩数据包数量。

    • 示例

      • 23:46:47eth0rxcmp/s0.00,表示一秒内,eth0 没有接收任何压缩数据包。

  8. txcmp/s

    • 含义:每秒发送压缩数据包数量。

    • 示例

      • 23:46:47eth0txcmp/s0.00,表示一秒内,eth0 没有发送任何压缩数据包。

  9. rxmcst/s

    • 含义:每秒接收多播数据包数量。

    • 示例

      • 23:46:47eth0rxmcst/s0.00,表示一秒内,eth0 没有接收任何多播数据包。

  10. %ifutil

    • 含义:网络接口利用率(百分比)。表示网络接口采样期间繁忙程度。

    • 示例

      • 23:46:47eth0%ifutil0.00,表示一秒内 ,eth0利用率非常低。

  11. Average:

    • 含义:表示所有采样时间平均值。

    • 示例

      • rxpck/seth0平均值1.00,表示采样期间,eth0 每秒平均接收 1 个数据包。

      • txpck/seth0平均值2.33,表示采样期间,eth0 每秒平均发送 2.33 个数据包。

      • rxkB/seth0平均值0.06,表示采样期间,eth0 每秒平均接收 0.06 KB 的数据。

      • txkB/seth0平均值0.38,表示采样期间,eth0 每秒平均发送 0.38 KB 的数据。

      • %ifutileth0平均值0.00,表示采样期间,eth0平均利用率非常低。

这个日志可以看出当前系统网络接口活动:

  • eth0采样期间一些网络活动,主要表现发送数据包(txpck/stxkB/s),但接收数据包少(rxpck/srxkB/s)。

  • lo(本地回环接口)和无线接口 wlan0wlan1采样期间没有任何网络活动。

  • 网络接口利用率(%ifutil)非常低,表明网络接口没有成为系统性能瓶颈。

sar 常用命令

默认监控 : sar 5 5     //  CPU  IOWAIT 统计状态 
sar -b 5 5        // IO 传送速率
sar -B 5 5        // 页交换速率
sar -c 5 5        // 进程创建的速率
sar -d 5 5        // 块设备的活跃信息
sar -n DEV 5 5    // 网路设备的状态信息
sar -n SOCK 5 5   // SOCK 的使用情况
sar -n ALL 5 5    // 所有的网络状态信息
sar -P ALL 5 5    // 每颗 CPU 的使用状态信息和 IOWAIT 统计状态 
sar -q 5 5        // 队列的长度(等待运行的进程数)和负载的状态
sar -r 5 5       // 内存和 swap 空间使用情况
sar -R 5 5       // 内存的统计信息(内存页的分配和释放、系统每秒作为 BUFFER 使用内存页、每秒被 cache 到的内存页)
sar -u 5 5       // CPU 的使用情况和 IOWAIT 信息(同默认监控)
sar -v 5 5       // inode, file and other kernel tablesd 的状态信息
sar -w 5 5       // 每秒上下文交换的数目
sar -W 5 5       // SWAP 交换的统计信息 ( 监控状态同 iostat  si so)
sar -x 2906 5 5  // 显示指定进程 (2906) 的统计信息,信息包括:进程造成的错误、用户级和系统级用户 CPU 的占用情况、运行在哪颗 CPU 上
sar -y 5 5       // TTY 设备的活动状态
将输出到文件 (-o) 和读取记录信息 (-f)

iozone

iozone一款开源工具,用来测试文件系统读写性能,也可以进行测试磁盘读写性能。

iozone详细说明可以参考本手册Iozone 章节。

iperf3

iperf3一个用于测试网络性能工具,可以测量 TCP 和 UDP 的带宽质量。它可以报告带宽、延迟抖动数据包丢失信息。

iperf3详细说明可以参考本手册iperf3 章节。

netstat

netstat( network statistics)命令是 Linux 和其他类 Unix 操作系统用于显示网络连接、路由表、接口统计信息、伪装连接多播成员网络相关信息工具。它一个强大命令行工具,广泛应用网络管理故障排除。

netstat 主要用来:

  • 显示活动的 TCP 连接、 UDP 连接、路由表、接口统计信息等。

  • 列出所有监听端口及其对应服务。

  • 显示网络接口统计信息。

  • 提供 IP 路由表信息。

  • 显示网络连接状态(如建立、监听、关闭等)。

netstat 的原理

netstat (Net Statistics) 主要通过读取操作系统网络信息,提供关于网络接字连接、监听端口、网络接口状态详细信息。netstat数据来源主要操作系统内核网络栈,包括 /proc/net 文件系统信息。

netstat 的参数说明

通过组合不同选项,可以查看网络各种状态信息、路由表、接口信息、连接状态信息,以下netstat 命令常用参数及其说明:

  • 基本选项:

    • -r, --route:显示路由表。

    • -i, --interfaces:显示网络接口表。

    • -g, --groups:显示多播组成员信息。

    • -s, --statistics:显示网络统计数据(类似 SNMP)。

    • -M, --masquerade:显示伪装连接。

  • 输出格式控制:

    • -v, --verbose:显示详细信息。

    • -W, --wide:不截断 IP 地址。

    • -n, --numeric:显示数字格式,不解析主机名、端口等。

    • --numeric-hosts:不解析主机名。

    • --numeric-ports:不解析端口名。

    • --numeric-users:不解析用户名。

    • -N, --symbolic:解析硬件名称。

    • -e, --extend:显示信息。

    • -p, --programs:显示每个接字对应进程 ID 或程序名。

    • -o, --timers:显示接字定时器信息。

    • -c, --continuous:持续显示输出。

  • 显示类型控制:

    • -l, --listening:显示监听服务器接字。

    • -a, --all:显示所有接字(默认显示连接接字)。

    • -F, --fib:显示转发信息库( FIB)。

    • -C, --cache:显示路由缓存。

  • Socket 类型选项

    • { -t|--tcp }:显示 TCP 协议连接。

    • { -u|--udp }:显示 UDP 协议连接。

    • { -U|--udplite }:显示 UDPLite 协议连接。

    • { -S|--sctp }:显示 SCTP 协议连接。

    • { -w|--raw }:显示原始接字连接。

    • { -x|--unix }:显示 Unix 域套接字连接。

    • --ax25, --ipx, --netrom:显示其他协议连接(如 AX.25 、 IPX、 NET/ROM 协议等)。

  • 地址选项

    • 默认: 使用 inet 地址族( IPv4 )。

    • IPv6: 使用 -6--ipv6显示 IPv6 地址。

    • IPv4: 使用 -4--ipv4显示 IPv4 地址。

  • 支持地址

    • inet: DARPA Internet( IPv4 )。

    • inet6: IPv6 。

    • ax25: AMPR AX.25 协议。

    • netrom: AMPR NET/ROM 协议。

    • rose: AMPR ROSE 协议。

    • ipx: Novell IPX 协议。

    • ddp: AppleTalk DDP 协议。

    • x25: CCITT X.25 协议。

netstat 的使用说明

使用语法

netstat [Options] [Address Families]

其中:

  • Options:用来指定查看信息类型其他行为。

  • Address Families:限制显示特定协议信息,如 -A inet 表示显示 IPv4 的信息。

基本用法

  • 列出所有当前网络连接

    netstat -a
    

    显示所有当前网络连接,包括 TCP、 UDP 和 Unix 域套接字。

  • 列出所有 TCP 连接

    netstat -at
    

    显示所有 TCP 协议连接。

  • 列出所有 UDP 连接

    netstat -au
    

    显示所有 UDP 协议连接。

  • 禁用反向域名解析

    netstat -ant
    

    禁用反向域名解析,直接显示 IP 地址端口号,加快查询速度。

  • 列出监听连接

    netstat -tnl
    

    显示所有处于监听状态的 TCP 端口。

  • 获取进程名、进程以及用户 ID

    netstat -tnlp
    

    显示每个连接对应进程 ID 和程序名称。需要 root 权限。

  • 显示内核路由信息

    netstat -rn
    

    显示内核路由表信息,禁用域名解析。

  • 打印网络接口信息

    netstat -ie
    

    显示网络接口详细信息,类似ifconfig 命令输出。

  • 持续输出网络连接信息

    netstat -ct
    

    持续输出 TCP 连接信息。

  • 显示多播信息

    netstat -g
    

    显示 IPv4 和 IPv6 的多播组成员信息。

netstat 示例

示例 1 :列出所有连接

通过 netstat -a 命令即可显示系统所有网络连接,包括互联网协议和 Unix 域套接字:

root@buildroot:~# netstat -a
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 0.0.0.0:30431           0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:telnet          0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:ssh             0.0.0.0:*               LISTEN
tcp        0    208 192.168.1.10:ssh        192.168.1.101:7428      ESTABLISHED
tcp        0      0 192.168.1.10:ssh        192.168.1.101:7429      ESTABLISHED
udp        0      0 192.168.1.10:ntp        0.0.0.0:*
udp        0      0 localhost:ntp           0.0.0.0:*
udp        0      0 0.0.0.0:ntp             0.0.0.0:*
udp        0      0 0.0.0.0:319             0.0.0.0:*
udp        0      0 0.0.0.0:320             0.0.0.0:*
Active UNIX domain sockets (servers and established)
Proto RefCnt Flags       Type       State         I-Node   Path
unix  2      [ ACC ]     SEQPACKET  LISTENING     7479     /run/udev/control
unix  2      [ ]         STREAM     CONNECTED     8305
unix  2      [ ]         DGRAM      CONNECTED     8281
unix  3      [ ]         STREAM     CONNECTED     8280
unix  3      [ ]         STREAM     CONNECTED     8279
unix  3      [ ]         STREAM     CONNECTED     4598
unix  3      [ ]         STREAM     CONNECTED     7524
unix  3      [ ]         STREAM     CONNECTED     7528     /run/dbus/system_bus_socket
unix  3      [ ]         STREAM     CONNECTED     8278
unix  3      [ ]         STREAM     CONNECTED     8277
unix  3      [ ]         STREAM     CONNECTED     7523
unix  3      [ ]         STREAM     CONNECTED     8275
unix  3      [ ]         STREAM     CONNECTED     8274
unix  2      [ ]         STREAM     CONNECTED     14501
unix  2      [ ]         DGRAM      CONNECTED     368
unix  3      [ ]         STREAM     CONNECTED     1854
unix  3      [ ]         STREAM     CONNECTED     1853
unix  2      [ ]         DGRAM      CONNECTED     1925
unix  6      [ ]         DGRAM      CONNECTED     1912     /dev/log
unix  3      [ ]         DGRAM      CONNECTED     10244
unix  3      [ ]         DGRAM      CONNECTED     10243
unix  2      [ ACC ]     STREAM     LISTENING     1815     /run/dbus/system_bus_socket
unix  2      [ ]         DGRAM      CONNECTED     10459
unix  2      [ ]         DGRAM                    1876     /var/run/ptp4l
unix  2      [ ]         DGRAM                    8240     /var/run/phc2sys.569
unix  2      [ ACC ]     STREAM     LISTENING     8276     @jdwp-control

以下详细说明:

  1. Active Internet connections (servers and established)

    • TCP 连接(传输控制协议)

      • 状态为 LISTEN 的连接

        • 0.0.0.0:30431:监听所有 IP 地址( 0.0.0.0 )上端口 30431 。没有指定远程连接,表示这是一个开放端口等待连接。

        • 0.0.0.0:telnet:监听所有 IP 地址的 telnet 服务(端口 23 )。同样没有指定远程连接,表示 telnet 服务正在监听所有地址连接。

        • 0.0.0.0:ssh:监听所有 IP 地址的 SSH 服务(端口 22 )。表示允许所有地址的 SSH 连接。

      • 状态为 ESTABLISHED 的连接

        • 192.168.1.10:ssh -> 192.168.1.101:7428192.168.1.10:ssh -> 192.168.1.101:7429:这两条建立的 SSH 连接,表示 192.168.1.101(远程主机)与机(192.168.1.10)的 SSH 连接,端口分别为 7428 和 7429 ,且已经处于建立状态,数据可以传输。

    • UDP 连接(用户数据协议)

      • 192.168.1.10:ntp:监听192.168.1.10的 NTP 服务(端口 123 ),允许接收所有远程的 NTP 请求。

      • localhost:ntp:监听本地回环接口( localhost)上的 NTP 服务。这通常用于时间同步。

      • 0.0.0.0:ntp:监听所有 IP 地址的 NTP 服务,允许任何来源的 NTP 请求。

      • 0.0.0.0:3190.0.0.0:320:这两个端口监听所有 IP 地址,但未指定协议目的地址,可能某些特定服务。

  2. Active UNIX domain sockets (servers and established)

    • UNIX 域套接字(用于进程间通信):

      • /run/udev/control:此套接字udev 系统管理守护进程用于控制设备接口,它在“ LISTENING”状态下,表示正在等待其他进程连接。

      • /run/dbus/system_bus_socket:这是 D-Bus 系统总线接字,多个进程系统总线进行通信。多个进程此套接字建立连接,显示为 “CONNECTED” 状态。

      • /dev/log:这表示机上日志守护进程(如 syslog)的 Unix 域套接字。它允许本地进程通过接字日志消息发送到系统日志守护进程。

      • /run/dbus/system_bus_socket(再次出现):在 Unix 域套接字部分出现这个路径,表示 D-Bus 系统总线接字多个连接中。

      • /var/run/ptp4l/var/run/phc2sys.569:这两个接字路径显示在 “ CONNECTED” 状态,表明它们属于特定时钟同步服务。

      • @jdwp-control:这是用于 Java 调试协议( JDWP)的接字,通常由 Java 调试器使用。它处于监听状态,表明系统中有进程可能正在等待调试连接。

    • 连接状态

      • LISTENING:表示服务等待连接。

      • CONNECTED:表示连接建立,数据可以两端之间传输。

      • DGRAM:表示数据报套接字,通常用于 UDP 类型通信,不保证可靠传输。

日志可以看出:

  • TCP 连接:本正在监听端口 30431 、 telnet(端口 23 )、 SSH(端口 22 )等,并且远程主机建立了 SSH 连接。

  • UDP 连接:本机上多个 NTP 服务端口正在监听,允许远程本地系统进行时间同步。

  • Unix 域套接字:多个进程通过 UNIX 域套接字系统服务(如 udev、 dbus、 syslog 等)通信,且存在一些调试接字。


示例 2 :列出路由表

通过 netstat -rn 命令可以显示当前主机路由表。netstat -rn 命令用于显示网络路由表信息,并且显示原始的(不经过 DNS 解析)路由信息。

root@buildroot:~# netstat -rn
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
0.0.0.0         192.168.1.1     0.0.0.0         UG        0 0          0 eth0
192.168.1.0     0.0.0.0         255.255.255.0   U         0 0          0 eth0

下面详细分析:

  1. 默认路由

    0.0.0.0         192.168.1.1     0.0.0.0         UG        0 0          0 eth0
    
    • Destination (目标地址): 0.0.0.0 表示这是一个默认路由。默认路由所有没有路由表明确列出目标地址通过路由进行转发。

    • Gateway (网关): 192.168.1.1 表示所有到达其他网络流量将会转发网关地址。通常 192.168.1.1局域网路由器网关设备的 IP 地址。

    • Genmask (子网掩码): 0.0.0.0 表示没有子网掩码要求,默认路由涉及具体子网掩码。

    • Flags (标志): UG 表示这个路由是“ Up”(活跃的)并且是“ Gateway”(网关路由),即该路由作为默认网关的。

    • MSS (最大报文大小): 0 表示没有指定最大传输单元。

    • Window (窗口大小): 0 表示没有设置窗口大小。

    • irtt (RTT 估算值): 0 表示没有设置往返时延( Round Trip Time)的估算值。

    • Iface (网络接口): eth0 表示路由条目适用eth0 网络接口。

  2. 局域网路由

    192.168.1.0     0.0.0.0         255.255.255.0   U         0 0          0 eth0
    
    • Destination (目标地址): 192.168.1.0 表示这是指向本地子网 192.168.1.0/24路由条目,/24 子网掩码表示本地网络地址范围是从 192.168.1.0192.168.1.255

    • Gateway (网关): 0.0.0.0 表示路由需要使用网关,属于本地网络路由。

    • Genmask (子网掩码): 255.255.255.0 表示子网掩码,定义192.168.1.0 网络地址范围。

    • Flags (标志): U 表示这个路由是“ Up”的,即该路由可用。

    • MSS (最大报文大小): 0 表示没有指定最大传输单元。

    • Window (窗口大小): 0 表示没有设置窗口大小。

    • irtt (RTT 估算值): 0 表示没有设置往返时延估算值。

    • Iface (网络接口): eth0 表示路由条目适用eth0 网络接口。

日志可以看出:

  • 默认路由 (0.0.0.0 -> 192.168.1.1): 所有明确指定目标流量转发192.168.1.1(通常本地网络网关路由器)。

  • 局域网路由 (192.168.1.0/24): 192.168.1.0 网段流量需要经过网关,直接本地网络接口 eth0进行通信。


示例3:显示处于监听状态网络连接

通过 netstat -tnl 命令可以显示所有处于监听状态网络连接。

root@buildroot:~#   netstat -tnl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 0.0.0.0:30431           0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:23              0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN

以下每个详细解释:

  1. 第一行 : tcp        0      0 0.0.0.0:30431           0.0.0.0:*               LISTEN

    • Proto (协议): tcp 表示端口使用是 TCP 协议。

    • Recv-Q (接收队列): 0 表示当前没有接收队列数据。

    • Send-Q (发送队列): 0 表示当前没有发送队列数据。

    • Local Address (本地地址): 0.0.0.0:30431 表示服务本地监听 30431 端口,0.0.0.0 表示它会接受来自任意 IP 地址连接请求。

    • Foreign Address (外部地址): 0.0.0.0:* 表示端口可以接受来自任意远程地址连接。

    • State (状态): LISTEN 表示端口处于监听状态,等待来自外部连接。

  2. 第二行 : tcp        0      0 0.0.0.0:23              0.0.0.0:*               LISTEN

    • Proto (协议): tcp 表示端口使用是 TCP 协议。

    • Recv-Q (接收队列): 0 表示当前没有接收队列数据。

    • Send-Q (发送队列): 0 表示当前没有发送队列数据。

    • Local Address (本地地址): 0.0.0.0:23 表示服务本地监听 23 端口(通常用于 Telnet 服务)。

    • Foreign Address (外部地址): 0.0.0.0:* 表示端口可以接受来自任意远程地址连接。

    • State (状态): LISTEN 表示端口处于监听状态,等待来自外部连接。

  3. 第三行 : tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN

    • Proto (协议): tcp 表示端口使用是 TCP 协议。

    • Recv-Q (接收队列): 0 表示当前没有接收队列数据。

    • Send-Q (发送队列): 0 表示当前没有发送队列数据。

    • Local Address (本地地址): 0.0.0.0:22 表示服务本地监听 22 端口(通常用于 SSH 服务)。

    • Foreign Address (外部地址): 0.0.0.0:* 表示端口可以接受来自任意远程地址连接。

    • State (状态): LISTEN 表示端口处于监听状态,等待来自外部连接。

日志可以看出:

  • 当前系统监听三个 TCP 端口:

    • 30431端口: 可能某个自定义服务。

    • 23端口: 用于 Telnet 服务,通常推荐生产环境使用,因为 Telnet 不加密通信。

    • 22端口: 用于 SSH 服务,允许远程安全登录。

这些端口监听状态,表示它们正在等待外部连接。

ss 的使用简介

ss (Socket Statistics) 命令可以用来获取 socket 统计信息,它可以显示和 netstat 类似内容。 ss 的优势在于能够显示详细有关 TCP 和连接状态信息,而且比 netstat 更快速高效。 ss 高效秘诀在于,它利用了 TCP 协议栈中 tcp_diag。 tcp_diag 是一个用于分析统计模块,可以获得 Linux 内核第一手信息,这确保了 ss 的快捷高效。

ss 的参数如下:

Usage: ss [ OPTIONS ]
       ss [ OPTIONS ] [ FILTER ]
   -h, --help          this message
   -V, --version       output version information
   -n, --numeric       don't resolve service names
   -r, --resolve       resolve host names
   -a, --all           display all sockets
   -l, --listening     display listening sockets
   -o, --options       show timer information
   -e, --extended      show detailed socket information
   -m, --memory        show socket memory usage
   -p, --processes     show process using socket
   -i, --info          show internal TCP information
       --tipcinfo      show internal tipc socket information
   -s, --summary       show socket usage summary
       --tos           show tos and priority information
       --cgroup        show cgroup information
   -b, --bpf           show bpf filter socket information
   -E, --events        continually display sockets as they are destroyed
   -Z, --context       display process SELinux security contexts
   -z, --contexts      display process and socket SELinux security contexts
   -N, --net           switch to the specified network namespace name

   -4, --ipv4          display only IP version 4 sockets
   -6, --ipv6          display only IP version 6 sockets
   -0, --packet        display PACKET sockets
   -t, --tcp           display only TCP sockets
   -M, --mptcp         display only MPTCP sockets
   -S, --sctp          display only SCTP sockets
   -u, --udp           display only UDP sockets
   -d, --dccp          display only DCCP sockets
   -w, --raw           display only RAW sockets
   -x, --unix          display only Unix domain sockets
       --tipc          display only TIPC sockets
       --vsock         display only vsock sockets
   -f, --family=FAMILY display sockets of type FAMILY
       FAMILY := {inet|inet6|link|unix|netlink|vsock|tipc|xdp|help}

   -K, --kill          forcibly close sockets, display what was closed
   -H, --no-header     Suppress header line
   -O, --oneline       socket's data printed on a single line
       --inet-sockopt  show various inet socket options

   -A, --query=QUERY, --socket=QUERY
       QUERY := {all|inet|tcp|mptcp|udp|raw|unix|unix_dgram|unix_stream|unix_seqpacket|packet|netlink|vsock_stream|vsock_dgram|tipc}[,QUERY]

   -D, --diag=FILE     Dump raw information about TCP sockets to FILE
   -F, --filter=FILE   read filter information from FILE
       FILTER := [ state STATE-FILTER ] [ EXPRESSION ]
       STATE-FILTER := {all|connected|synchronized|bucket|big|TCP-STATES}
         TCP-STATES := {established|syn-sent|syn-recv|fin-wait-{1,2}|time-wait|closed|close-wait|last-ack|listening|closing}
          connected := {established|syn-sent|syn-recv|fin-wait-{1,2}|time-wait|close-wait|last-ack|closing}
       synchronized := {established|syn-recv|fin-wait-{1,2}|time-wait|close-wait|last-ack|closing}
             bucket := {syn-recv|time-wait}
                big := {established|syn-sent|fin-wait-{1,2}|closed|close-wait|last-ack|listening|closing}

详细说明可以参考 ss 官方文档

性能诊断工具使用总结

常用系统性能监控工具进行分类总结如下:

  1. CPU 监控命令

    • top:实时显示系统各个进程资源占用情况。

    • vmstat:报告关于进程、内存、分页、块 I/O、陷阱和 CPU 活动信息。

    • mpstat:显示每个可用 CPU 使用情况报告。

    • pidstat:报告每个进程的 CPU 使用情况。

    • uptime:提供系统整体运行状态信息,包括 CPU 负载情况。

    • sar:统计 CPU 的使用情况,也可以查看 CPU 平均负载。

  2. 内存监控命令

    • free:显示系统空闲使用物理内存交换空间。

    • top:同上,也可以用来监控内存使用情况。

    • pidstat:同上,也可以用来监控内存使用情况。

    • vmstat:同上,也可以用来监控内存使用情况。

    • sar:查看内存使用情况。

  3. IO 性能

    • iostat:报告 CPU 和输入 / 输出统计信息。

    • vmstat:同上,也可以用来监控 IO 性能。

    • sar:收集、报告存储系统活动信息,包括 IO 性能。

    • iozone

  4. 网络性能

    • iperf3:网络性能测试工具。

    • netstat:显示网络连接、路由表、接口统计信息。

    • sar:统计各种网络信息。

其他性能分析工具介绍

国际知名性能分析专家 Brendan Gregg(性能分析工具火焰发明人)总结了 Linux 系统性能分析工具:

Linux_performance_tool

张图展示了 Linux 性能工具生态系统,涵盖硬件应用程序各个层面。图中将工具分为几个主要类别:可观测工具、静态性能工具、应用程序配置工具、系统调用接口工具、文件系统工具、调度工具、虚拟内存工具、时钟工具、设备驱动工具、固件工具、网络控制器工具、 I/O 控制器工具、 I/O 桥接工具、 CPU 工具、内存工具、 DRAM 工具、 GPU 工具、 I/O 工具、 FAN 工具电源工具。

以下各个部分简要介绍:

  1. 观测工具 这些工具用于系统负载观察系统状态。

    • 文件系统lsof, pcstat, df -h, dmesg, mdadm, lvm, dmsetup, trace, pidstat -d

    • 磁盘iostat, iotop, strace

    • 交换空间lshw, lscsil, blockdev, swapon -s, smartctl, fdisk -l, /proc/swaps

  2. 静态性能工具 这些工具可以系统空闲观察系统状态。

    • BPF (Berkeley Packet Filter)perf, ftrace, funccount, funclatency, stackcount, kprobe, uprobe, argdist, trace, profile

    • 文件系统ext4slower, ext4dist, btrfs*, xfs*, zfs*

    • 磁盘cachestat, dcsnoop, filetop, fileslower, mountsnoop

  3. 应用程序配置工具 这些工具用于配置监控应用程序。

    • strace, perf trace, syncnoop, sysdig, opensnoop, statsnoop, ugc ucalls

  4. 系统调用接口工具 这些工具用于监控分析系统调用。

    • 接字tcptop, tcplife, tcpconnect, tcpaccept, tcpconnlat, tcpretrans

    • TCP/UDPmysqld_glower, gethostlatency

    • IPldd, ltrace

    • 以太网ifconfig, ethtool, ethtool -l, ipconfig

    • 设备驱动sar, perf, dstat, dmesg, journalctl, lsmod

    • 固件/sys/..., perf, dmesg, tiptop

  5. 文件系统工具

    • VFS (虚拟文件系统)lsof, pcstat, df -h, dmesg, mdadm, lvm, dmsetup, trace, pidstat -d

    • 文件系统multipath, mdflush

  6. 调度工具

    • cpupid, execsnoop, runlat, cpudist, offcputime, latencytop, schedtool

  7. 虚拟内存工具

    • mpstat, powertop, top, htop, ps, pidstat, vmstat, slabtop, free, /proc/meminfo

  8. 时钟工具

    • memleak, oomkill, slabratetop, numactl

  9. 设备驱动工具

    • ss, tcpdump, ip, route, iptables, iptraf-ng, dmesg

  10. 固件工具

    • biosnoop, bpftrace, biosnoop, bitsize

  11. 网络控制器工具

    • lscpci, lsusb, ethtool, ifconfig

  12. I/O 控制器工具

    • iostat, iotop, strace

  13. I/O 桥接工具

    • nicstat, netstat, ip

  14. CPU 工具

    • turbostat, rdmsr, cpuid, lscpu, llcstat, lstopo, capable

  15. 内存工具

    • intel_gpu_top, intel_gpu_time, intel_gpu_frequency, numactl, memstat, lstopo

  16. DRAM 工具

    • dramstat, dmidecode

  17. GPU 工具

    • intel_gpu, gputop, nvidia-smi

  18. I/O 工具

    • iostat, iotop, strace

  19. FAN 工具

    • sar -m, fan, dmidecode

  20. 电源工具

    • powertop

关于这些工具详细介绍可以在 Brendan Gregg 的博客 Linux Performance查看。

4.4.12.3. 系统优化策略

CPU 优化

CPU 优化策略主要集中以下几个方面:

  1. 进程优先级管理:通过合理调整进程优先级,确保重要进程获得足够的 CPU 时间,避免低优先级进程影响系统性能。

  2. 减少上下文切换:通过优化任务进程管理,减少频繁上下文切换,提升 CPU 使用效率。

  3. CPU 亲和性优化:通过关键进程绑定特定的 CPU 核心上,减少 CPU 迁移,提高处理效率。

  4. 实时性优化:通过启用实时内核补丁调整调度策略,减少任务切换延迟,确保实时任务及时执行。

这些策略主要适用需要并发、低延迟高性能计算系统环境,特别对于实时性要求应用多任务处理环境,能够显著提升 CPU 的性能系统整体响应能力。

调整进程优先级

  • 命令nicerenice用来调整进程优先级命令。nice启动进程设置优先级,renice 用于动态调整运行进程优先级。

  • 目的:合理分配 CPU 时间。通过调整进程优先级,可以确保重要进程获得多 CPU 时间,而重要进程可以让步,这有助于提升系统整体响应性能。

  • 适用场景:在进程多任务环境中,可能出现某些进程需要其他进程的 CPU 资源。通过调整优先级,可以避免低优先级进程占用过多资源,影响优先级进程执行。

  • 示例

    # 启动一个进程并设定较低的优先级(高 nice 值)
    nice -n 10 command
    # 修改已运行进程的优先级
    renice -n -10 -p <pid>
    

减少上下文切换

  • 上下文切换:是指 CPU 在多个进程线程之间切换时,保存加载执行状态(即上下文)的过程。频繁上下文切换增加 CPU 的负担,并导致性能下降。

  • 策略

    • 合并过多任务:如果系统中有大量任务(如频繁线程创建销毁),它们导致大量上下文切换。通过调整线程大小、合并任务方式,可以减少上下文切换频率。

    • 检查 pid_max进程限制pid_max 参数控制最大进程数,如果系统进程数过多,可能导致频繁调度管理,浪费 CPU 资源。适当限制进程数,避免过多无用进程占用资源,可以减少上下文切换。

  • 适用场景:在多任务并发环境中,过多任务进程导致频繁上下文切换,从而降低整体性能。减少无用进程任务,有助于提升系统响应速度资源使用效率。

CPU 亲和性

  1. 定义工作原理

    • CPU 亲和性(CPU Affinity):指将进程线程绑定特定的 CPU 或 CPU 集合上,使得进程线程指定的 CPU 上运行。这样主要目的提高进程运行效率。

    • 原理:进程运行时会在 CPU 缓存保留一定残余信息。如果一次运行进程时,能够同一 CPU 上执行,就利用这些缓存信息,避免缓存命中情况,从而减少 CPU 处理负担,提升性能。

  2. 亲和性亲和性

    • 亲和性:操作系统调度器(如 Linux 调度器)会自动倾向进程保持同一个 CPU 上运行,而频繁迁移。这样可以减少进程多个 CPU 之间切换,降低资源消耗,提高系统整体性能。

    • 亲和性:用户可以通过系统 API 手动指定进程运行哪个 CPU 上,从而满足特定性能需求。例如,在系统中,某些进程可以固定特定核心运行,避免调度干预。

  3. 系统默认调度优化

    • 一般情况下, Linux 系统调度已经具备优化能力,默认调度策略能够平衡负载性能,适用大多数应用程序。

    • 然而,针对特定应用,尤其性能要求极高任务,系统通用调度策略可能不能达到最佳效果。这时,通过使用 CPU 亲和性,用户可以手动优化特定进程运行效率。

  4. 命令 taskset应用

    • 命令taskset 是 Linux 系统一个命令,用于进程绑定特定的 CPU 核心上,从而避免进程多个 CPU 核心之间频繁迁移(即“ CPU 迁移”)。通过这一方法,可以显著减少由于频繁迁移导致缓存失效调度开销。

    • 目的:通过固定进程特定核心运行,减少 CPU 核心迁移,避免调度开销,提高计算效率。

    • 适用场景:对于性能要求任务,特别需要频繁计算进程,可以使用 taskset 命令进程绑定特定 CPU 核心,从而避免多核调度产生性能损耗。

    • 示例

      # 将进程绑定到第一个 CPU 核心上
      taskset -c 0 <command>
      
  5. 应用场景

    • 高密度计算进程:对于一些计算密集型进程,如果希望多个 CPU 核心频繁切换,可以通过 CPU 亲和性固定某个特定核心上,减少调度开销。

    • 高频交易场景:例如,在股票期货高频交易中,交易策略执行速度至关重要。即便是 1ms 的延迟可能带来显著经济损失。通过交易策略线程绑定专用的 CPU 上,可以避免线程切换性能损失,确保及时响应。

    • 高性能 Web 服务器(如 Nginx):在多线程架构下,通过固定 worker 进程特定的 CPU 核心,能够减少 CPU 切换损耗,从而提升服务器处理能力响应速度。

    • 虚拟化技术:在 KVM 虚拟化环境中,通过优化 CPU 亲和性,可以显著减少虚拟机网络延迟,在牺牲吞吐量情况下,提升虚拟化环境性能。

实时性优化

  • 实时内核补丁(如 PREEMPT_RT)

    • PREEMPT_RT 是一个 Linux 内核补丁,旨在提高内核实时性能,减少任务切换延迟,使得进程能够快速响应外部事件,确保重要任务及时执行。

  • 调整调度策略:通过调整调度策略,可以优化 CPU 在不同任务切换效率。例如,实时任务可能需要普通任务优先级延迟。

  • 目的:减少任务切换延迟,提升系统响应速度,尤其需要高度实时性应用,如音视频处理、实时数据采集等。

  • 适用场景:对于要求实时性应用,启用实时内核优化调度策略可以大大提高系统响应性,确保时间关键任务及时执行。

  • 示例:可以通过内核配置启用 PREEMPT_RT 补丁,并使用实时调度策略(如 SCHED_FIFO)来确保任务优先执行。

内存优化

内存优化策略主要集中以下几个方面:

  • Swap 管理:通过调整 vm.swappiness 参数、使用 SSD 作为 Swap 设备或者禁用 Swap,可以有效提高系统内存性能,避免频繁磁盘 I/O 操作对系统性能影响。

  • 透明大页(THP):禁用可能引发延迟的 THP 可以避免负载带来不必要性能损失,同时可以根据需要启用禁用大页提高内存管理效率。

  • OOM Killer 配置:通过调整 oom_score_adj 参数确保关键进程内存紧张杀死,优先保护系统重要应用,保证系统稳定运行。

Swap 管理

  • vm.swappiness 调整

    • vm.swappiness 是 Linux 系统一个内核参数,用来控制系统使用 Swap 空间倾向。 Swap 是硬盘一个空间,用来存储暂时活跃内存数据。系统内存压力增大时,将部分内存数据交换到 Swap 中。

    • 默认情况下,vm.swappiness 设置为 60 ,表示系统使用 Swap。如果该值调低(如设置为 10 ),系统倾向内存压力时候使用物理内存,而急于使用 Swap。这样可以避免 Swap 空间过早使用,提升内存响应速度。

    • 示例:通过 sysctl -w vm.swappiness=10 调整该值为 10 ,表示减少系统使用 Swap 的倾向,优先使用物理内存。

  • 使用 SSD 作为 Swap

    • 如果确实需要使用 Swap,建议选择 SSD 等高性能存储设备作为 Swap 分区。传统机械硬盘读写速度于 SSD 慢很多,频繁的 Swap 操作可能导致严重性能瓶颈,影响系统响应整体性能。使用 SSD 可大幅提高 Swap 访问速度,缓解 I/O 性能瓶颈。

  • 禁用 Swap

    • 某些场景下,为了避免磁盘 I/O 对性能影响,可能考虑完全禁用 Swap。磁盘 I/O 操作远慢内存访问,尤其系统频繁进行 Swap 操作时,可能导致系统性能大幅下降。禁用 Swap 可以避免系统内存数据交换磁盘,从而保证内存响应速度。

透明大页( THP)

  • 透明大页(Transparent Huge Pages, THP)

    • 大页( HugePages)是一种内存管理技术,可以减少内存页表开销,特别处理大量内存时,能显著提高内存访问性能。

    • 透明大页(THP)一种自动化技术,可以程序运行自动常用内存合并内存块,从而减少内存管理开销,提升性能。

    • 然而,透明大页某些情况可能引起延迟,尤其负载、高并发场景中。此时,禁用 THP 可以避免由 THP 引发性能下降。

    • 示例:通过 echo never > /sys/kernel/mm/transparent_hugepage/enabled 禁用透明大页( THP)。

    • 说明:当前系统默认没有开启 THP 功能, Kernel menuconfig 中没有开启 TRANSPARENT_HUGEPAGE 配置项。

OOM Killer 配置

  • OOM Killer:在 Linux 系统中,当内存使用达到极限时, OOM Killer 会启动,它会根据一套策略选择某个进程杀死,以释放内存。系统优先杀死那些消耗内存进程。

  • oom_score_adj 参数

    • 每个进程一个 oom_score_adj 参数,用来调整进程被 OOM Killer 杀死优先级。oom_score_adj高,表示进程杀死优先级越低,反之越高。

    • 通过修改 /proc/<pid>/oom_score_adj 文件,可以调整某个进程oom_score,确保关键任务核心进程内存不足不会被 OOM Killer 杀死。

    • 例如,给核心进程设置oom_score,就确保它们内存耗尽优先保留,系统杀死其他重要进程释放内存。 示例 : 假设一个关键进程 1234 ,希望内存不足优先保留它,可以的 oom_score_adj 设置为 1000 (注意需要有 root 权限):

      echo 1000 > /proc/1234/oom_score_adj
      

      假设一个非关键进程 5678 ,希望内存不足优先杀死它,可以的 oom_score_adj 设置为 -1000 (注意需要有 root 权限):

      echo -1000 > /proc/5678/oom_score_adj
      

      调整后,可以通过以下命令验证设置是否生效:

      cat /proc/1234/oom_score_adj
      cat /proc/5678/oom_score_adj
      

存储优化

嵌入式 Linux 系统中,由于主要使用是 eMMC 或 NAND SPI Flash 存储,因此优化策略应当重点关注以下方面:

  • 文件系统选择:选择闪存设计文件系统,如 UBIFS 或 F2FS,以及启用 noatime 选项,减少不必要写入。

  • I/O 调度选择:使用适合闪存调度器(如 noop 或 kyber),减少 I/O 调度复杂性,提高系统响应速度。

  • 减少操作:通过使用 tmpfs 存储临时文件压缩日志文件,减少频繁闪存写入。

  • 闪存磨损均衡:通过优化程序写入行为,避免频繁写入热点,延长闪存寿命。

  • 启用 TRIM 支持:定期运行 TRIM 操作,清理无用数据块,保持闪存高效性能。

文件系统选择

  • 适合闪存文件系统

    • UBIFSF2FS闪存设备(如 eMMC 和 NAND Flash)专门设计文件系统。这些文件系统能够有效管理闪存读写操作,并优化性能耐用性。例如, F2FS 通过减少频繁擦写操作延长闪存寿命,而 UBIFS 则通过优化写入垃圾回收机制提高闪存存储效率。

    • 选择这些文件系统有助于减少传统文件系统(如 ext4 )在闪存不足,确保闪存设备写入密集场景维持较长使用寿命。

  • 启用 noatime 选项

    • noatime 选项用于防止系统每次访问文件更新访问时间。通常,文件系统每次读取文件更新文件atime,这会引起不必要写入操作,尤其频繁访问文件上。在闪存频繁写入加速磨损,因此启用 noatime 可以有效减少写入次数,延长闪存寿命。

    • 通过修改 /etc/fstab 文件添加 noatime 选项,可以减少不必要访问时间写入。 修改示例

      • 查看当前配置状态

        root@buildroot:/userdata# cat /etc/fstab
        # <file system> <mount pt>      <type>  <options>       <dump>  <pass>
        /dev/root       /               ext2    rw,noauto       0       1
        proc            /proc           proc    defaults        0       0
        devpts          /dev/pts        devpts  defaults,gid=5,mode=620,ptmxmode=0666   0       0
        tmpfs           /dev/shm        tmpfs   mode=0777       0       0
        tmpfs           /tmp            tmpfs   mode=1777       0       0
        tmpfs           /run            tmpfs   mode=0755,nosuid,nodev  0       0
        sysfs           /sys            sysfs   defaults        0       0
        debugfs         /sys/kernel/debug debugfs defaults      0       0
        tmpfs           /data           tmpfs   mode=1777       0       0
        
      • 相关挂载添加 noatime 选项 例如,如果文件系统 / 启用 noatime,可以/etc/fstab条目修改为:

        /dev/root       /               ext2    rw,noatime,noauto       0       1
        
      • 使能配置 修改完后,保存文件重新挂载文件系统,或者重启系统,新挂载选项生效。重新挂载命令可以使用:

        sudo mount -o remount / 
        

I/O 调度选择

  • I/O 调度选择

    • 对于 eMMC 和 NAND 闪存设备,推荐使用 noopkyber 调度器。这些调度比较简单,并且闪存设备上能减少不必要延迟。

      • noop 调度器:它基本进行复杂队列管理,适合闪存设备,因为闪存设备本身具有访问延迟。

      • kyber 调度器:它比 noop 更智能一点,但同样复杂调度计算,适合延迟需求场景。

    • 使用这些简单调度可以提高性能减少延迟,因为它们需要进行复杂调度计算,这对于 I/O 较为简单闪存设备非常有利。

    • 查看当前系统调度方式:

      • 通过查看内核启动日志,可以了解系统支持的 I/O 调度类型。运行以下命令:

        dmesg | grep -i scheduler
        

        示例:

        root@buildroot:~# dmesg | grep -i scheduler
        [    0.000000] rcu: RCU calculated value of scheduler-enlistment delay is 10 jiffies.
        [    0.351393] io scheduler mq-deadline registered
        [    0.351399] io scheduler kyber registered
        

        结果可以看出,当前系统mq-deadline 以及 kyber I/O 调度已经注册用于设备。

      • 查看当前使用的 I/O 调度类型。运行以下命令:

        # 对于 EMMC 执行
        cat /sys/block/mmcblk0/queue/scheduler
        # 对于 NAND Flash 执行
        cat /sys/block/sda/queue/scheduler
        

        示例:

        root@buildroot:~# cat /sys/block/mmcblk0/queue/scheduler
        [mq-deadline] kyber none
        

        日志可以看出系统设备 mmcblk0 配置多种 I/O 调度选项,当前正在使用的 I/O 调度器是 mq-deadline(因为方括号 [ ] 包裹起来了),当前系统支持 kybernone 两种 I/O 调度器:

        • mq-deadline:这是当前激活的 I/O 调度器。 mq-deadline一种队列( multi-queue) I/O 调度器,它是 deadline 调度改进版本,适用队列存储设备(如 NVMe SSD)。它旨在减少 I/O 延迟,提高响应速度。

        • kyber:这一种可用的 I/O 调度器,但当前激活。 kyber 是一种相对的 I/O 调度器,旨在提供更好的 I/O 性能公平性。

        • none:表示没有使用任何 I/O 调度器。这通常用于某些特殊场景,例如设备本身已经具备高效的 I/O 管理机制时。

    • 修改当前系统调度方式: 可以通过以下命令动态修改(需要 root 权限):

      echo "kyber" > /sys/block/mmcblk0/queue/scheduler
      

      或者:

      echo "none" > /sys/block/mmcblk0/queue/scheduler
      

      注意,修改 I/O 调度可能影响系统性能,建议测试环境进行调整,并根据实际需求选择合适调度器。

减少操作

  • 使用 tmpfs

    • tmpfs一种基于内存文件系统,常用存储临时数据。通过临时文件、缓存文件、日志存储在 RAM 中,可以避免频繁进行操作到 eMMC 或 NAND 闪存中。

    • /tmp其他临时目录挂载tmpfs 可以大大减少闪存写入压力,尤其负载嵌入式系统中,临时文件频繁读写可能影响闪存寿命。

      # 挂载 tmpfs
      mount -t tmpfs tmpfs /tmp
      
  • 日志文件压缩

    • 对于嵌入式系统生成日志文件,考虑定期压缩清理过时日志文件,以避免日志文件不断增加导致大量写入闪存。日志文件通常频繁写入,如果加以控制,可能加速闪存磨损。

闪存磨损均衡

  • 闪存写入次数限制

    • eMMC 和 NAND 闪存设备具有有限写入次数,每个存储单元一定次数写入逐渐失效。为了延长闪存寿命,需要减少操作避免频繁写入热点。

    • 通过优化程序写入行为、减少不必要随机写入,并热点数据合理分布闪存不同区域,可以有效减少某些区域写入频率,帮助实现磨损均衡。

启用 TRIM 支持

  • TRIM 操作

    • TRIM一个用于闪存设备命令,它可以帮助操作系统告知闪存哪些数据不再使用,从而闪存能够进行擦除操作,释放空间优化性能。 TRIM 操作可以帮助减少闪存垃圾数据,保持存储空间高效利用。

    • 如果系统启用了 TRIM 的支持,可以定期运行 fstrim 命令,可以清理无用数据块,延长闪存使用寿命提高性能。

    • 说明

      当前系统默认支持 TRIM 功能:

      root@buildroot:~#  lsblk --discard
      NAME         DISC-ALN DISC-GRAN DISC-MAX DISC-ZERO
      mtdblock0           0        0B       0B         0
      mmcblk0             0      512B     3.5M         0
      |-mmcblk0p1         0      512B     3.5M         0
      |-mmcblk0p2         0      512B     3.5M         0
      |-mmcblk0p3         0      512B     3.5M         0
      |-mmcblk0p4         0      512B     3.5M         0
      |-mmcblk0p5         0      512B     3.5M         0
      |-mmcblk0p6         0      512B     3.5M         0
      |-mmcblk0p7         0      512B     3.5M         0
      |-mmcblk0p8         0      512B     3.5M         0
      |-mmcblk0p9         0      512B     3.5M         0
      |-mmcblk0p10        0      512B     3.5M         0
      |-mmcblk0p11        0      512B     3.5M         0
      |-mmcblk0p12        0      512B     3.5M         0
      `-mmcblk0p13        0      512B     3.5M         0
      mmcblk0boot0        0      512B     3.5M         0
      mmcblk0boot1        0      512B     3.5M         0
      

      DISC-GRAN (discard granularity) 和 DISC-MAX (discard max bytes) 列非 0 表示存储设备支持 TRIM 功能。

网络优化

网络优化策略主要围绕三个方面:

  1. TCP 连接优化:通过调整端口范围启用 TIME_WAIT 回收,提高网络连接复用端口可用性,特别适用并发场景。

  2. 多核 CPU 网络吞吐量优化:通过启用 RSS 和 IRQ 绑定,提升网卡接收数据包处理能力,减少 CPU 瓶颈。

  3. 资源限制优化:通过调整 nofilenproc 限制,确保系统能够处理并发连接进程,适用负载、高并发服务器环境。

这些优化方案并发、高吞吐量网络服务尤为重要,能够显著提升系统性能稳定性。

TCP 参数调优

  • 增大本地端口范围

    • 命令sysctl -w net.ipv4.ip_local_port_range="1024 65535"

    • 目的:增大本地端口范围,避免端口耗尽。通常情况下,操作系统限制本地端口范围。如果并发连接数高,可能导致本地端口用尽,特别需要频繁发起大量连接时(例如并发网络应用)。通过增大端口范围,可以保证应用能够使用可用端口,避免端口短缺导致连接失败。

    • 适用场景:高并发网络应用,特别需要频繁建立连接场景(如高并发 Web 服务、数据库连接池等)。

  • 启用 TIME_WAIT 连接回收

    • 命令sysctl -w net.ipv4.tcp_tw_reuse=1

    • 目的:启用 TIME_WAIT 状态连接回收。 TCP 在关闭连接进入 TIME_WAIT 状态,这会占用本地端口,特别并发环境可能导致端口资源耗尽。启用配置后,系统回收处于 TIME_WAIT 状态连接,提升端口复用利用率,避免端口耗尽。

    • 适用场景:高并发服务器场景,特别连接频繁建立连接应用(如负载均衡、 Web 服务器等)。

网卡队列

  • 启用 RSS(接收端扩展)并绑定 IRQ 到不同 CPU

    • 目的:启用 RSS 能够使网卡接收数据包分配多个 CPU 核心,充分利用多核 CPU 提高网络吞吐量。通常网络流量通过单一核心进行处理,可能导致瓶颈。通过接收数据包分配多个 CPU 内核进行处理,可以有效减少 CPU 负载提高整体网络处理能力。

    • 适用场景:高带宽、高流量网络应用,尤其服务器环境下,启用 RSS 可以显著提高网络吞吐量,减少瓶颈。

    • 补充说明:绑定 IRQ 到不同的 CPU 核心可以进一步优化 CPU 利用率,防止某个核心过度负载。

连接数限制

  • 调整 nofilenproc 限制

    • 命令:对于嵌入式 Linxu 系统可以通过修改 /etc/profile 文件调整 nofile(文件描述符)和 nproc(进程数)限制。

    • 目的

      • nofile:限制系统每个进程可以打开文件描述符数量,增加限制可以允许并发连接文件操作。

      • nproc:限制系统每个用户可以创建最大进程数,增大限制能够允许用户启动进程,适用需要启动大量进程场景。

    • 适用场景:高并发服务,特别需要大量并发连接网络应用(如 Web 服务器、数据库连接池、大规模分布式应用等)。

    • 配置示例

      sudo vi /etc/profile
      # 添加下面内容
      ulimit -n 65536  # 设置最大文件描述符数
      ulimit -u 65536  # 设置最大进程数
      

4.4.12.4. 应用优化

应用编码优化策略,主要聚焦性能提升内存管理方面。

Coding 原则

  • 避免巨量函数调用(核心循环尽量使用 inline 函数)

    • 策略分析:函数调用引入一定开销,尤其核心循环频繁调用时。使用 inline 函数可以编译函数代码直接嵌入调用处,从而减少函数调用开销,提升性能。对于性能要求代码段,尤其循环频繁执行函数,使用 inline 可以显著提高效率。

    • 注意:过度使用 inline 可能导致代码膨胀,尤其函数较大情况下,因为每次调用代码复制到调用点,可能增加二进制文件体积。

  • 循环无关代码外提

    • 策略分析:循环代码尽量包含循环必需计算,避免每次迭代执行相关计算。循环外提代码那些依赖于循环变量每次迭代重复执行操作移出循环,从而减少冗余计算。这样可以有效提升程序性能,尤其循环次数较多时。

  • 避免不必要内存引用操作

    • 策略分析:内存访问操作通常比较耗时的,尤其对于延迟内存访问(如磁盘读取数据、访问远程内存等)。优化内存引用意味着减少不必要数据访问重复访问相同数据。通过合理缓存内存管理,可以减少内存带宽消耗,提高数据处理速度。

守护线程优化

守护线程优化目标通过减少数量简化代码降低资源占用,提升系统性能稳定性。优化守护线程能够减少内存使用,并避免资源管理瓶颈。

核心策略减少守护线程数量,简化代码

  • 策略分析

    • 守护线程后台运行,通常参与业务逻辑,因此占用过多资源。线程多,占用系统资源越大。

    • 代码复杂度守护线程增加计算、内存分配管理开销,进而影响性能。

    • 避免性能瓶颈,应减少守护线程数量优化代码,以减少内存占用,减轻系统调度资源管理压力,提升整体性能。

  • 风险

    • 长时间运行守护线程可能引发内存泄漏,因内存分配释放不易察觉,导致内存占用无法释放。

    • 并发长时间运行系统中,内存泄漏可能快速累积,降低性能,甚至崩溃。

    • 因此,需要定期检查清理守护线程资源,避免内存泄漏,确保系统稳定运行。

动态加载优化

动态加载优化策略主要减少动态加载数量,从而优化程序启动时间、内存占用运行性能。

减少无用动态加载

  • 策略分析:去掉不必要动态库。通过减少不必要库,程序启动开销内存占用减少。这是一个非常直接有效优化方式。

  • 影响:去除不必要库后,程序加载库会减少,进程内存占用、加载时间符号查找能够得到优化,减少不必要工作。

重新组织动态结构

  • 策略分析:通过重新组织结构减少加载动态数量,目的避免多个之间冗余加载。每个应该加载必须部分,避免过多相互依赖。

  • 影响:这个方法有助于提升效率,减少加载数量,进而减少符号查找、动态链接运行开销。

动态编译静态

  • 优点

    • 减少加载动态数量,因为静态编译合并可执行文件中,不再需要程序运行加载。

    • 动态其他合并后,内部函数调用不再需要符号查找、动态链接,避免这些开销。

  • 缺点

    • 占用内存:当静态多个进程其他依赖时,它会复制多份,导致内存占用增加。由于静态直接嵌入程序中,不能动态那样共享内存代码段。

    • 影响性能:每个进程加载自己静态副本,导致内存浪费。同时,由于静态增加进程内存需求,可能导致 page fault 增多,从而影响程序加载速度运行效率。

  • 适用情况:当某些动态库仅少数进程使用时,编译静态可以减少启动加载开销。然而,对于常驻守护进程动态库,静态反而不如动态高效。

使用 dlopen 动态加载动态

  • 优点

    • 精确控制动态生命周期dlopen 使得程序能够加载动态库,而不是程序启动加载所有依赖库。这可以减少启动时间,并且根据需要动态管理加载卸载。

    • 减少内存使用:通过 dlopen 动态加载库,可以使用卸载库,减少内存中未使用部分。对于一些常用库,这样加载节省内存。

  • 影响

    • 使用 dlopen 可能增加程序复杂性,因为需要手动管理加载卸载。这意味着开发者必须保证不再需要库时及时调用 dlclose,以避免内存泄漏其他资源问题。

    • 此外,dlopen 可能增加额外性能开销,尤其进行符号解析时。如果没有优化得当,可能导致性能下降。

4.4.12.5. USE 方法介绍

USE 方法核心内容

USE 方法( Utilization Saturation and Errors Method)是国际知名性能分析专家 Brendan Gregg(性能分析工具火焰发明人)提出一种用于系统性能分析高效方法论,旨在快速识别解决系统资源瓶颈。 USE 方法核心通过检查系统每个资源利用率( Utilization)、饱和度( Saturation)和 错误率( Errors)来快速定位性能问题。这种方法论目的性能调查早期阶段,快速识别系统性瓶颈。

通过以下三个关键指标分析系统资源:

  1. Utilization(利用率)

    • 资源忙于处理工作时间百分比。

    • 例如, CPU 使用率、磁盘 I/O 使用率。

  2. Saturation(饱和度)

    • 资源过载排队等待程度(资源超出服务能力额外工作量,通常表现队列长度)。

    • 例如, CPU 运行队列长度、磁盘 I/O 等待队列。

  3. Errors(错误率)

    • 资源发生错误数量频率。

    • 例如,网络丢包、磁盘 I/O 错误。

USE 方法适用下面场景:

  • 系统性能调优。

  • 容量规划资源分配。

  • 故障排查根因分析。

USE 方法具有下面优势:

  • 快速定位问题:通过简单指标快速识别性能瓶颈。

  • 全面覆盖:适用硬件软件资源,覆盖系统各个层面。

  • 易于实施:只检查三个指标,适合所有用户群体。

USE 方法流程说明

  1. 列出所有资源

    • 包括 CPU、内存、磁盘、网络硬件资源,以及软件资源(如线程池、连接池)。

  2. 检查每个资源USE 指标

    • 每个资源,依次检查利用率、饱和度错误。

  3. 识别瓶颈

    • 根据 USE 指标,快速定位性能瓶颈。

  4. 深入分析

    • 针对瓶颈资源,使用详细工具方法进行深入分析。

USE 方法具体流程如下:

Steps of USE Method

下面流程图各个步骤详细解释:

  1. 开始(Start)

    • 流程这里开始,准备进行性能分析。

  2. 识别资源(Identify Resources)

    • 确定需要检查系统资源,包括 CPU、内存、磁盘、网络硬件资源,以及线程池、连接池软件资源。

  3. 选择资源(Choose a Resource)

    • 识别资源列表选择一个资源进行分析。

  4. 错误存在吗?(Errors Present?)

    • 检查选定资源是否存在错误。如果存在错误( Y),则进行一步错误调查。

    • 如果没有错误( N),则继续检查资源利用率。

  5. 利用率?(High Utilization?)

    • 检查选定资源利用率是否过高。如果利用率高( Y),则可能存在性能瓶颈,需要进一步调查。

    • 如果利用率不高( N),则继续检查资源饱和度。

  6. 饱和度?(Saturation?)

    • 检查选定资源是否存在饱和度问题。如果存在饱和度( Y),则表明资源可能无法处理工作负载,需要进一步调查。

    • 如果没有饱和度( N),则继续检查一个资源。

  7. 所有资源检查完毕?(All Resources Fully Checked?)

    • 检查是否所有资源检查。如果所有资源检查( Y),则流程结束。

    • 如果还有资源检查( N),则返回步骤 3 ,继续选择一个资源进行检查。

  8. 识别问题(Identified the Problem?)

    • 调查过程中,检查是否已经识别问题。如果已经识别问题( Y),则返回步骤 3 ,继续检查其他资源结束流程。

    • 如果尚未识别问题( N),则继续进行调查发现( Investigate Discovery)。

  9. 调查发现(Investigate Discovery)

    • 如果前面步骤发现问题,但尚未识别问题根本原因,则进行深入调查发现,以确定问题根本原因。

  10. 结束(End)

    • 流程结束,所有资源检查,问题(如果存在)已识别。

基于 USE 理论性能分析步骤

深入理解 USE 方法之后,我们通过一组常用的 Linux 工具,快速掌握系统性能关键指标。这些工具能够命令行界面提供系统性能初步概览,用户执行以下 10 个命令,便短时间大致了解系统资源使用情况运行进程信息。

这些命令重点关注系统错误饱和度指标,因为两类指标易于理解,又有效帮助快速定位问题。通过这些工具,用户可以进一步探究资源利用情况,从而全面应用 USE 方法进行深入分析。

以下这 10 个命令及其功能简介:

  • uptime:显示系统平均负载运行时间,帮助了解系统负载状况。

  • dmesg | tail:查看系统日志最新几条消息,便于获取可能错误警告信息。

  • vmstat 1:每秒显示一次系统虚拟内存、进程和 I/O 等统计信息。

  • mpstat -P ALL 1:每秒显示所有 CPU 核心使用情况,帮助检测 CPU 负载。

  • pidstat 1:每秒显示进程资源使用情况,帮助找出资源占用进程。

  • iostat -xz 1:每秒显示 I/O 设备使用情况,重点关注空闲时间设备。

  • free -m:以 MB 为单位显示系统内存使用情况。

  • sar -n DEV 1:每秒显示网络设备性能统计信息。

  • sar -n TCP,ETCP 1:每秒显示 TCP 网络连接统计信息。

  • top:实时显示系统资源占用最高进程,便于及时识别资源消耗较大进程。

需要注意是,部分命令依赖于 sysstat 软件包。因此,用户使用之前需要在 Buildroot 中启用 sysstat 相关配置:

BR2_PACKAGE_SYSSTAT=y

然后,重新编译文件系统,关于 Buildroot 的详细内容可以参考本手册 使用 Buildroot 制作文件系统 章节。

通过这些命令收集指标,用户可以有效运用 USE 方法进行系统性能分析。此外,用户关注分析时机,明确何时排除某些资源影响。通过排除法,逐步缩小调查范围,从而后续深入分析指明方向。

USE 方法指标列表

Brendan Gregg 为 USE 方法论总结一个 指标列表 ,涵盖各种物理资源,如 CPU、内存、网络接口、存储设备 I/O、存储容量、存储控制器、网络控制器、 CPU 互连、内存互连和 I/O 互连等。对于每种资源,文章列出相应指标用于收集这些指标命令行工具。

例如:

  • CPU 利用率:使用 vmstat 1sar -udstat -c命令。

  • 内存利用率:使用 free -mvmstat 1sar -rdstat -m命令。

  • 网络接口利用率:使用 sar -n DEV 1ip -s link/proc/net/dev命令。

  • 存储设备 I/O 利用率:使用 iostat -xz 1sar -d命令。

详细表格如下:

component type metric
CPU utilization system-wide: vmstat 1, "us" + "sy" + "st"; sar -u, sum fields except "%idle" and "%iowait"; dstat -c, sum fields except "idl" and "wai"; per-cpu: mpstat -P ALL 1, sum fields except "%idle" and "%iowait"; sar -P ALL, same as mpstat; per-process: top, "%CPU"; htop, "CPU%"; ps -o pcpu; pidstat 1, "%CPU"; per-kernel-thread: top/htop ("K" to toggle), where VIRT == 0 (heuristic). [1]
CPU saturation system-wide: vmstat 1, "r" > CPU count [2]; sar -q, "runq-sz" > CPU count; dstat -p, "run" > CPU count; per-process: /proc/PID/schedstat 2nd field (sched_info.run_delay); perf sched latency (shows "Average" and "Maximum" delay per-schedule); dynamic tracing, eg, SystemTap schedtimes.stp "queued(us)" [3]
CPU errors perf (LPE) if processor specific error events (CPC) are available; eg, AMD64's "04Ah Single-bit ECC Errors Recorded by Scrubber" [4]
Memory capacity utilization system-wide: free -m, "Mem:" (main memory), "Swap:" (virtual memory); vmstat 1, "free" (main memory), "swap" (virtual memory); sar -r, "%memused"; dstat -m, "free"; slabtop -s c for kmem slab usage; per-process: top/htop, "RES" (resident main memory), "VIRT" (virtual memory), "Mem" for system-wide summary
Memory capacity saturation system-wide: vmstat 1, "si"/"so" (swapping); sar -B, "pgscank" + "pgscand" (scanning); sar -W; per-process: 10th field (min_flt) from /proc/PID/stat for minor-fault rate, or dynamic tracing [5]; OOM killer: dmesg | grep killed
Memory capacity errors dmesg for physical failures; dynamic tracing, eg, SystemTap uprobes for failed malloc()s
Network Interfaces utilization sar -n DEV 1, "rxKB/s"/max "txKB/s"/max; ip -s link, RX/TX tput / max bandwidth; /proc/net/dev, "bytes" RX/TX tput/max; nicstat "%Util" [6]
Network Interfaces saturation ifconfig, "overruns", "dropped"; netstat -s, "segments retransmited"; sar -n EDEV, drop andfifo metrics; /proc/net/dev, RX/TX "drop"; nicstat "Sat" [6]; dynamic tracing for other TCP/IP stack queueing [7]
Network Interfaces errors ifconfig, "errors", "dropped"; netstat -i, "RX-ERR"/"TX-ERR"; ip -s link, "errors"; sar -n EDEV, "rxerr/s" "txerr/s"; /proc/net/dev, "errs", "drop"; extra counters may be under /sys/class/net/...; dynamic tracing of driver function returns 76]
Storage device I/O utilization system-wide: iostat -xz 1, "%util"; sar -d, "%util"; per-process: iotop; pidstat -d; /proc/PID/sched "se.statistics.iowait_sum"
Storage device I/O saturation iostat -xnz 1, "avgqu-sz" > 1, or high "await"; sar -d same; LPE block probes for queue length/latency; dynamic/static tracing of I/O subsystem (incl. LPE block probes)
Storage device I/O errors /sys/devices/.../ioerr_cnt; smartctl; dynamic/static tracing of I/O subsystem response codes [8]
Storage capacity utilization swap: swapon -s; free; /proc/meminfo "SwapFree"/"SwapTotal"; file systems: "df -h"
Storage capacity saturation not sure this one makes sense - once it's full, ENOSPC
Storage capacity errors strace for ENOSPC; dynamic tracing for ENOSPC; /var/log/messages errs, depending on FS
Storage controller utilization iostat -xz 1, sum devices and compare to known IOPS/tput limits per-card
Storage controller saturation see storage device saturation, ...
Storage controller errors see storage device errors, ...
Network controller utilization infer from ip -s link (or /proc/net/dev) and known controller max tput for its interfaces
Network controller saturation see network interface saturation, ...
Network controller errors see network interface errors, ...
CPU interconnect utilization LPE (CPC) for CPU interconnect ports, tput / max
CPU interconnect saturation LPE (CPC) for stall cycles
CPU interconnect errors LPE (CPC) for whatever is available
Memory interconnect utilization LPE (CPC) for memory busses, tput / max; or CPI greater than, say, 5; CPC may also have local vs remote counters
Memory interconnect saturation LPE (CPC) for stall cycles
Memory interconnect errors LPE (CPC) for whatever is available
I/O interconnect utilization LPE (CPC) for tput / max if available; inference via known tput from iostat/ip/...
I/O interconnect saturation LPE (CPC) for stall cycles
I/O interconnect errors LPE (CPC) for whatever is available

Brendan Gregg 建议用 USE 方法指标列表监控 Linux 系统时,可以按照以下步骤操作:

  1. 确定监控目标:首先,明确需要监控系统资源,如 CPU、内存、磁盘网络等。

  2. 选择适当工具:根据监控目标,从文章提供指标列表选择合适命令行工具。例如,可以使用 vmstat监控 CPU 利用率,使用 iostat监控磁盘 I/O 利用率,使用 sar监控网络接口利用率等。

  3. 收集性能数据:运行选定工具收集性能数据。例如,要检查 CPU 利用率,可以使用以下命令:

    • vmstat 1:显示每秒的 CPU 和系统资源使用情况。

    • mpstat -P ALL 1:显示所有 CPU 的使用情况。

    • tophtop:显示进程级别的 CPU 使用情况。

    • pidstat 1:显示每个进程的 CPU 使用情况。

  4. 分析性能数据:分析收集数据,识别利用率( Utilization)、饱和度( Saturation)和错误( Errors)。例如,可以检查 vmstat 输出的“ r”值是否大于 CPU 核心数,这可能表明 CPU 饱和。

  5. 识别瓶颈错误:通过分析,识别系统性能瓶颈错误。例如,如果发现 CPU 利用率过高,可能需要进一步调查是否进程占用的 CPU 资源。

  6. 采取行动:根据分析结果,采取相应优化措施。这可能包括调整系统配置、优化应用程序升级硬件资源。

  7. 定期监控:将性能监控作为常规维护一部分,定期检查系统性能,以确保及时发现解决潜在问题。

  8. 深入分析延迟分析:如果完成这个检查表仍然遇到性能问题,可以继续使用其他策略,如深入分析延迟分析。

4.4.12.6. 案例分析

以高 CPU 负载场景为例,对性能分析以及优化过程进行说明。

编写测试用例

编写测试用例模拟 CPU 性能瓶颈几种常见情景,它包括以下部分:

  • 负载任务模拟:通过执行密集计算任务模拟 CPU 高负载。

  • 上下文切换频繁模拟:通过创建大量线程它们频繁切换模拟上下文切换瓶颈。

  • 中断处理过多模拟:通过模拟硬件中断观察 CPU 处理中断情况。

例如下:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#include <time.h>
#include <sched.h>
#include <math.h>

#define NUM_THREADS 100   // 线程数量
#define MAX_TASK_COUNT 10000000000  // 每个线程的任务数量
#define MEDIUM_TASK_COUNT 1000000  // 每个线程的任务数量

// 高负载任务模拟
void* simulate_high_load_task(void* arg) {
    printf("Starting high load task...\n");

    // 高精度时间测量
    struct timespec start, end;
    double cpu_time_used;

    // 获取当前时间作为开始时间
    clock_gettime(CLOCK_MONOTONIC, &start);

    // 执行复杂计算(大规模矩阵乘法或大规模计算)
    for (long long i = 0; i < MAX_TASK_COUNT; i++) {
        int result = (i * i + i) % 999999;  // 更复杂的计算
    }

    // 获取结束时间
    clock_gettime(CLOCK_MONOTONIC, &end);

    // 计算任务执行时间(单位:秒)
    cpu_time_used = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / 1e9;

    // 打印任务执行时间
    printf("High load task completed in %f seconds.\n", cpu_time_used);
    return NULL;
}

// 线程函数
void* thread_function(void* arg) {
    int id = *(int*)arg;
    free(arg);  // 释放线程编号的内存
    printf("Thread %d started.\n", id);
    for (int i = 0; i < MEDIUM_TASK_COUNT; i++) {
        // 执行简单的计算任务
        int result = i * i;

        // 模拟线程主动放弃 CPU,触发上下文切换
        usleep(100);  // 休眠 100 微秒
    }
    printf("Thread %d finished.\n", id);
    return NULL;
}

// 上下文切换频繁模拟
void* simulate_context_switching(void* arg) {
    pthread_t threads[NUM_THREADS];

    printf("Starting %d threads...\n", NUM_THREADS);
    for (int i = 0; i < NUM_THREADS; i++) {
        int* thread_id = malloc(sizeof(int));
        *thread_id = i;
        if (pthread_create(&threads[i], NULL, thread_function, thread_id) != 0) {
            perror("Failed to create thread");
            exit(EXIT_FAILURE);
        }
    }

    for (int i = 0; i < NUM_THREADS; i++) {
        if (pthread_join(threads[i], NULL) != 0) {
            perror("Failed to join thread");
            exit(EXIT_FAILURE);
        }
    }

    printf("All threads completed.\n");
    return NULL;
}

// 模拟中断处理函数
void handle_interrupt(int sig) {
    static int count = 0;
    printf("Interrupt %d handled\n", ++count);
    // 执行一些计算任务,模拟 CPU 密集型工作
    for (int i = 0; i < 100; i++) {
        // 执行一些计算任务
        int result = i * i;
    }
}

// 模拟硬件中断
void* simulate_hardware_interrupt(void* arg) {
    printf("Starting hardware interrupt simulation...\n");
    signal(SIGALRM, handle_interrupt);

    // 每 10 us 触发一次中断,模拟频繁的硬件中断
    // 第一次触发的时间
    struct itimerval timer;
    timer.it_value.tv_sec = 0;
    timer.it_value.tv_usec = 10;  // 10us
    // 设置定时器周期 
    timer.it_interval.tv_sec = 0;
    timer.it_interval.tv_usec = 10;  // 每 10us 触发一次
    setitimer(ITIMER_REAL, &timer, NULL);

    while (1) {
        // 等待信号触发
        pause();
    }
    return NULL;
}

// 主函数
int main(int argc, char* argv[]) {
    if (argc < 2) {
        printf("Usage: %s <test_cases>\n", argv[0]);
        printf("Test cases:\n");
        printf("  1: High load task\n");
        printf("  2: Context switching\n");
        printf("  3: Hardware interrupt\n");
        return 1;
    }

    pthread_t threads[4];
    int test_cases[4] = {0};

    for (int i = 1; i < argc; i++) {
        int test_case = atoi(argv[i]);
        if (test_case < 1 || test_case > 3) {
            printf("Invalid test case number: %d\n", test_case);
            return 1;
        }
        test_cases[test_case - 1] = 1;
    }

    if (test_cases[0]) {
        pthread_create(&threads[0], NULL, simulate_high_load_task, NULL);
    }
    if (test_cases[1]) {
        pthread_create(&threads[1], NULL, simulate_context_switching, NULL);
    }
    if (test_cases[2]) {
        pthread_create(&threads[0], NULL, simulate_high_load_task, NULL);
        pthread_create(&threads[2], NULL, simulate_hardware_interrupt, NULL);
    }

    for (int i = 0; i < 3; i++) {
        if (test_cases[i]) {
            pthread_join(threads[i], NULL);
        }
    }

    return 0;
}

编译应用:

arm_gcc simulate_cpu_bottleneck.c -o simulate_cpu_bottleneck -pthread -lm

其中 arm_gcc.bashrc创建编译工具别名:

# ~/.bashrc
alias arm_gcc='/opt/arm-gnu-toolchain-11.3.rel1-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-gcc'

测试分析

编译simulate_cpu_bottleneck 转存板端 /userdata 目录,然后执行 chmod +x simulate_cpu_bottleneck 赋予执行权限,即可按照下面命令进行测试:

  • ./simulate_cpu_bottleneck 1:高负载任务模拟。

  • ./simulate_cpu_bottleneck 2:上下文切换频繁模拟

  • ./simulate_cpu_bottleneck 3:中断处理过多模拟。

下面分别进行分析。

负载任务模拟

执行 ./simulate_cpu_bottleneck 1 后,将模拟一个负载计算任务,可以按照 USE 方法介绍工具查看 CPU 的变化。


  • top 命令

    执行 top 命令可以看到如下界面:

    High_load_task_simulation

    分析其中关键输出:

    %Cpu6  : 100.0/0.0   100[||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||]
    
    • %Cpu6: 表示 CPU 核心 6 的使用情况。

      • 100.0/0.0:

        • 第一个数字 100.0 表示 CPU 核心 6 完全这个进程占用了( 100% 的用户时间),即所有计算能力进程消耗。

        • 第二个数字 0.0 表示没有内核态 CPU 时间使用,也就是说,该进程没有进行系统操作,它完全执行用户级别计算任务。

    • 100: 该进程正在占用核心 6 的 100% 资源,这反映对 CPU 的负载影响。

    • [||||… ]: 该条进度条可视化显示,表示进程对 CPU 资源占用程度,这里几乎满条,显示进程几乎完全占用该 CPU 核心。

    4466 root      20   0   74.8m   0.3m 100.0   0.0   3:15.18 S              `- ./simulate_cpu_bottleneck 1
    
    • 4466: 这是进程的 PID(进程 ID),表明这是系统运行进程。

    • root: 进程所有者,这里root 用户。

    • 20: 进程优先级。

    • 0: 进程的 nice 值(用于调整进程优先级)。

    • 74.8m: 进程使用物理内存,表示占用了 74.8 MB 内存。

    • 0.3m: 进程使用虚拟内存(包括代码、数据堆栈)。

    • 100.0: 进程使用的 CPU 百分比,这意味着进程正在使用 100% 的 CPU 时间。

    • 0.0: 进程的 I/O 等待时间(等待磁盘、网络等 I/O 操作)。这里显示为 0 ,表示进程没有等待 I/O。

    • 3:15.18: 进程累计 CPU 时间( 3 小时 15 分钟 18 秒),表明进程运行较长时间。

    • S: 进程状态, S 表示进程处于“睡眠”状态,但由于只是等待 CPU 时间,实际上活跃执行任务。

    • - ./simulate_cpu_bottleneck 1: 这是进程命令行,其中 ./simulate_cpu_bottleneck 1启动任务命令。

    现象解释:

    • CPU 满负荷:从 %Cpu6来看,进程正在完全占用 CPU 核心 6 ,导致使用 100% 的计算能力。进程可能影响其他进程性能,特别系统只有少数 CPU 核心时。

    • 长时间运行:进程已经运行较长时间( 3 小时 15 分钟 18 秒),这意味着一个计算密集型任务,可能需要大量时间完成。

    • 内存使用:尽管进程正在消耗大量 CPU 资源,但内存使用量( 74.8 MB)相对低,表示计算需求主要是 CPU 密集型,而不是内存密集型。


  • vmstat 命令

    执行 vmstat 1 命令,每秒更新一次系统统计信息。重点关注 cpu 部分内容,尤其%user(用户态 CPU 时间)和 %sys(内核态 CPU 时间)。在执行负载任务时,%user 会变高。

    获取日志如下:

    root@buildroot:~# vmstat 1
    procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
    r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
    0  0      0 1041108  16612  64552    0    0     2     0   53   54 42  0 58  0  0
    0  0      0 1041108  16612  64552    0    0     0     0  189  231  0  1 99  0  0
    0  0      0 1041108  16612  64552    0    0     0     0   42   57  0  0 100  0  0
    0  0      0 1041108  16612  64552    0    0     0     0   91  112  0  0 100  0  0
    0  0      0 1041108  16612  64552    0    0     0     0   79   99  0  0 99  0  0
    0  0      0 1041108  16612  64552    0    0     0    12   75   99  0  0 100  0  0
    0  0      0 1041108  16612  64552    0    0     0     0   73   88  0  0 100  0  0
    0  0      0 1041108  16612  64552    0    0     0     0  107  100  0  1 99  0  0
    0  0      0 1041108  16612  64552    0    0     0     0   41   54  0  0 100  0  0
    
    # 执行 ./simulate_cpu_bottleneck 1 时刻
    
    1  0      0 1041108  16612  64552    0    0     0     0  171  149  4  1 96  0  0
    2  0      0 1041108  16612  64552    0    0     0     0  159   65 13  0 87  0  0
    1  0      0 1041108  16612  64552    0    0     0     0  270  203 13  0 87  0  0
    1  0      0 1041108  16612  64552    0    0     0    12  208  125 13  0 87  0  0
    1  0      0 1041108  16612  64552    0    0     0     0  170   74 13  0 88  0  0
    1  0      0 1041108  16612  64552    0    0     0     0  201   94 13  0 87  0  0
    1  0      0 1041108  16612  64552    0    0     0     0  186   92 13  0 87  0  0
    1  0      0 1041108  16612  64552    0    0     0     4  158   67 12  0 87  0  0
    1  0      0 1041108  16612  64552    0    0     0     0  196  102 13  0 87  0  0
    1  0      0 1041108  16612  64552    0    0     0     0  183   83 12  0 87  0  0
    1  0      0 1041108  16612  64552    0    0     0    12  171   83 13  0 87  0  0
    1  0      0 1041108  16612  64552    0    0     0     0  213  100 13  0 87  0  0
    1  0      0 1041108  16612  64552    0    0     0     0  196  101 13  0 87  0  0
    1  0      0 1041108  16612  64556    0    0     0     0  145   58 12  0 88  0  0
    1  0      0 1041108  16612  64556    0    0     0     0  196  106 13  0 87  0  0
    1  0      0 1041108  16612  64556    0    0     0     0  195   90 12  1 87  0  0
    1  0      0 1041108  16612  64556    0    0     0     0  155   68 13  0 88  0  0
    1  0      0 1041108  16612  64556    0    0     0    12  243  133 12  0 87  0  0
    1  0      0 1041108  16612  64556    0    0     0     0  203   93 13  0 87  0  0
    1  0      0 1041108  16612  64556    0    0     0     0  150   56 13  0 87  0  0
    

    执行测试用例后,系统状态发生些许变化,分析如下:

    • 初始状态(没有瓶颈时)

    0  0      0 1041108  16612  64552    0    0     0     0   41   54  0  0 100  0  0
    
    • CPU

      • us=0%:用户空间没有占用 CPU。需要注意,这里 us整个 CPU 所有核心总和值。

      • sy=0%:内核空间没有占用 CPU。

      • id=100%: 100% 的 CPU 时间空闲的,表示没有任何 CPU 负载。

    此时,系统没有发生 CPU 负载,所有进程等待 CPU 使用时, CPU 的空闲时间达到了 100%。

    • 执行 simulate_cpu_bottleneck状态

    1  0      0 1041108  16612  64552    0    0     0     0  170   74 13  0 88  0  0
    
    • 进程

      • r=1:有 1 个进程( simulate_cpu_bottleneck )在运行等待 CPU 时间,表示现在一个进程占用了 CPU。

      • b=0:没有进程阻塞,所有进程正常运行。

    • CPU

      • us=13%:用户空间现在占用了 13% 的 CPU (整个 CPU 所有核心总和)时间,表示模拟程序正在进行一些计算任务,占用 CPU。

      • sy=0%:内核空间几乎没有占用 CPU,内核负载轻。

      • id=88%:空闲 CPU 时间从 100% 降到了 88%,仍有 88% 的 CPU 时间空闲,但已经一些 CPU 负载。

    • 变化分析: 通过 ./simulate_cpu_bottleneck 1 命令,模拟一个轻微的 CPU 负载。这个命令作用可能启动一个持续占用 CPU 的进程,因此:

      • CPU 使用率上升us=13% 表示 CPU 在进行用户计算任务。

      • 空闲时间减少:空闲时间最初的 100% 减少了 88%。这表明 CPU 开始占用,但相当空闲时间。

    结论: 执行 ./simulate_cpu_bottleneck 1 后,系统进入一个轻微的 CPU 负载状态(因为 CPU 有 8 个核心,当前进程只会一个核心):

    • CPU 使用:有 13% 的用户空间 CPU 使用,空闲时间为 88%。

    • 进程:有一个进程运行占用 CPU(r=1),没有阻塞进程。

    • 内存:内存使用情况没有明显变化,系统依然保持健康内存状态。


  • uptime 命令

    执行 uptime 命令显示负载平均值,日志如下:

    01:56:00 up  1:56,  3 users,  load average: 1.00, 0.68, 2.48
    

    分析如下:

    • 当前时间 01:56:00: 当前系统时间凌晨 1 点 56 分 0 秒。

    • 系统运行时间 up 1:56: 系统已经启动运行了 1 小时 56 分钟。这个数字告诉系统上次启动以来经过多少时间。

    • 当前登录用户数 3 users: 当前有 3 个用户登录系统中。这通常包括所有远程用户本地用户。

    • 负载均值(Load Average) load average: 1.00, 0.68, 2.48: 负载均值系统过去 1 分钟、 5 分钟和 15 分钟平均负载。这三个数字分别表示过去 1 分钟、 5 分钟和 15 分钟系统平均负载。

      • 1.00 (1分钟): 过去 1 分钟负载是 1.00 。这意味着系统平均有 1 个进程等待 CPU 时间正在使用 CPU。如果系统只有 1 个核心, 1.00 表示系统的 CPU 利用率达到了 100%,但多个核心情况下,这个负载可以更高,而不会造成 CPU 超负荷。

        X5 总共有 8 个核心可以并行处理任务,所以负载 1.00 是非常轻松的,相当于平均每个核心忙碌处理一个任务。这个值远低于核心数,因此系统负载非常轻,不会性能瓶颈。

      • 0.68 (5分钟): 过去 5 分钟负载是 0.68 。这个负载低于 1.00 ,表明段时间内,系统负载轻,没有超过系统处理能力。

      • 2.48 (15分钟): 过去 15 分钟负载是 2.48 。相比于 1 分钟和 5 分钟负载,过去 15 分钟负载高,接近 2.5 。但系统有 8 个核心,负载为 2.48 表示大部分时间里,每个核心需要处理少量任务,因此系统依然能够轻松应对这种负载。

    负载均值解释:

    负载均值衡量系统处理任务能力,通常系统 CPU 核心数量一个参考指标。一般来说,负载均值等于接近 CPU 核心数时,系统的 CPU 就达到满负荷,超过核心数会导致进程积压,可能出现性能下降。

    • 如果系统1 个核心,那么 1.00 的负载意味着系统 CPU 已经充分使用(没有空闲)。如果负载更高(比如 2.48 ),则表示系统超过 1 个进程同时等待执行。

    • 如果系统多个核心,例如 8 个核心,负载为 2.48 则意味着 CPU 负载没有达到系统最大处理能力。 8 个核心可以轻松处理负载 2.48 ,系统仍然能够保持平稳运行。

    负载过高标准:

    • 8 个核心 的系统最大负载应为 8.00 。如果负载均值接近超过 8.00 ,那么可能进程开始排队,系统性能可能出现瓶颈,导致延迟。

    • 负载为 2.48 ,表示系统达到核心最大负载, CPU 资源充足,系统不会出现性能问题。

    结论:

    • 根据日志,系统负载均值低于 8 个核心最大负载,表明当前系统负载非常轻松, CPU 资源充裕。

    • 即使过去 15 分钟负载值( 2.48 )也不会对系统性能造成压力,系统足够处理能力应对当前任务。


  • mpstat 命令

    mpstat 命令可以输出各个 CPU 核心使用情况,详细说明每个核心各项 CPU 时间指标。

    root@buildroot:~# mpstat -P ALL 1
    Linux 6.1.83-DR-PL5.1_V1.0.16 (buildroot)       01/01/70        aarch64       (8 CPU)
    
    01:56:45     CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
    01:56:46     all   12.47    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00   87.53
    01:56:46       0    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00
    01:56:46       1    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00
    01:56:46       2    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00
    01:56:46       3  100.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00
    01:56:46       4    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00
    01:56:46       5    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00
    01:56:46       6    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00
    01:56:46       7    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00
    

    命令输出说明如下:

    • 系统信息

    Linux 6.1.83-DR-PL5.1_V1.0.16 (buildroot)       01/01/70        _aarch64_       (8 CPU)
    

    系统使用Linux 6.1.83 内核,架构aarch64,共有 8 个 CPU 核心

    • 总体的 CPU 使用情况

    01:56:45     CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
    01:56:46     all   12.47    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00   87.53
    
    • all:表示所有核心总和。

      • %usr=12.47%: 12.47% 的 CPU 时间用于执行用户空间进程(非内核进程)。

      • %nice=0.00%:没有进程调整优先级( nice)的方式运行。

      • %sys=0.00%:没有 CPU 时间用于内核空间操作。

      • %iowait=0.00%:没有等待 I/O 操作时间。

      • %irq=0.00%:没有 CPU 时间用于处理中断。

      • %soft=0.00%:没有 CPU 时间用于处理中断。

      • %steal=0.00%:没有 CPU 时间虚拟化系统抢占。

      • %idle=87.53%: 87.53% 的时间 CPU 处于空闲状态。

    all来看,系统的 CPU 使用情况非常轻松,大部分时间 CPU 都处于空闲状态。

    • 各个核心的 CPU 使用情况

      01:56:46       0    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00
      01:56:46       1    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00
      01:56:46       2    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00
      01:56:46       3  100.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00
      01:56:46       4    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00
      01:56:46       5    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00
      01:56:46       6    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00
      01:56:46       7    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00
      

      一行表示一个 CPU 核心使用情况,从 CPU 0 到 CPU 7(共 8 个核心)。

      • 核心 0 到 2 、 4 到 7 :

        • %usr=0.00%:这些核心用户空间的 CPU 时间为 0%,意味着没有用户进程这些核心运行。

        • %idle=100%:这些核心完全处于空闲状态,没有任务运行, CPU 处于空闲状态。

      • 核心 3 :

        • %usr=100.00%:核心 3 完全用户进程占用,所有的 CPU 时间用于执行用户空间进程。

        • %idle=0.00%:核心 3 没有空闲时间,完全忙碌处理任务。

      综上可以看出:

      1. CPU 总体使用情况

        • 系统12.47% CPU 时间用于用户空间任务,87.53% 时间空闲,说明系统负载轻,大部分时间 CPU 没有充分利用。

      2. 各个核心分布情况

        • 核心 3负载非常高,几乎 100% 的时间处理用户进程。其他核心(如核心 0 到 2 、 4 到 7 )几乎处于空闲状态,这可能表明某个特定任务进程集中核心 3 上运行。

      3. 没有 I/O 或中断等待

        • iowaitirqsoftirq是 0 ,表示系统没有因 I/O 操作中断导致 CPU 等待。

    结论

    • 系统这个时刻负载非常轻松,大多数 CPU 核心空闲,只有一个核心(核心 3 )被 100% 占用。

    • 系统整体性能非常平稳,没有出现瓶颈,空闲资源充足。如果这个状态持续,系统资源使用较为均衡。

    实现 mpstat 命令类似效果可以执行 sar -P 命令:

    root@buildroot:~# sar -P ALL 5 5
    Linux 6.1.83-DR-PL5.1_V1.0.16 (buildroot)       01/01/70        _aarch64_       (8 CPU)
    
    02:26:06        CPU     %user     %nice   %system   %iowait    %steal     %idle
    02:26:11        all     12.51      0.00      0.18      0.00      0.00     87.32
    02:26:11          0      0.00      0.00      0.00      0.00      0.00    100.00
    02:26:11          1      0.00      0.00      0.00      0.00      0.00    100.00
    02:26:11          2      0.00      0.00      0.00      0.00      0.00    100.00
    02:26:11          3    100.00      0.00      0.00      0.00      0.00      0.00
    02:26:11          4      0.00      0.00      0.00      0.00      0.00    100.00
    02:26:11          5      0.20      0.00      1.40      0.00      0.00     98.40
    02:26:11          6      0.00      0.00      0.00      0.00      0.00    100.00
    02:26:11          7      0.00      0.00      0.00      0.00      0.00    100.00
    
    02:26:11        CPU     %user     %nice   %system   %iowait    %steal     %idle
    02:26:16        all     12.57      0.00      0.10      0.03      0.00     87.30
    02:26:16          0      0.00      0.00      0.20      0.20      0.00     99.60
    02:26:16          1      0.00      0.00      0.00      0.00      0.00    100.00
    02:26:16          2      0.00      0.00      0.00      0.00      0.00    100.00
    02:26:16          3    100.00      0.00      0.00      0.00      0.00      0.00
    02:26:16          4      0.00      0.00      0.00      0.00      0.00    100.00
    02:26:16          5      0.60      0.00      0.60      0.00      0.00     98.80
    02:26:16          6      0.00      0.00      0.00      0.00      0.00    100.00
    02:26:16          7      0.00      0.00      0.00      0.00      0.00    100.00
    

  • 优化策略

    通过上述几个工具即可监控分析 CPU 的负载情况,可以观察负载任务对 CPU 的影响,特别是 CPU 使用率增加。进行性能分析时候需要通过多种命令查看 CPU 的整体使用状态以及各个 CPU 核使用状态。

    执行负载任务时,常见现象主要包括:

    • %user%sys 值,表示大量用户内核计算。

    • tophtop某个进程占用大量的 CPU 资源。

    • iowaitidle 时间低,表明 CPU 大量处于活跃状态,较少有空闲时间。

    实际工程情景中,如果遇到类似情况需要进行性能优化,可以考虑以下策略:

    • 减少计算复杂度:分析负载任务代码逻辑,寻找可以优化算法数据结构,减少不必要计算。

    • 并行任务:将任务分解多个任务,并行执行充分利用多核 CPU 的优势。例如,使用多线程异步编程模型。

上下文切换频繁模拟

执行 ./simulate_cpu_bottleneck 2 后,将模拟一个频繁触发上下文切换情景,上下文切换通常发生以下几种情况:

  • 时间片用:线程运行一段时间后,时间片用完,操作系统切换其他线程。

  • 等待资源:线程主动调用 sleep 或等待 I/O 操作,操作系统切换其他线程。

  • 线程同步:线程之间通过其他同步机制进行通信,导致线程阻塞切换。

为了实现高频率上下文切换,设计测试用例包含多个线程,每个线程执行简单任务,并且频繁调用 sleep 来模拟线程同步产生大量上下文切换。

可以通过下面工具查看上下文切换状态。


  • top 命令

    执行 top 命令可以看到如下界面:

    High_CS_simulation

    以下对系统当前状态分析:

    CPU 使用情况 系统有 8 个 CPU 核心,分别Cpu0Cpu7。每个核心使用情况如下:

    • %CpuX 统计数字分为部分:

      • 第一部分(例如 3.1 )是当前的 CPU 使用率。

      • 第二部分(例如 80.9 )是 CPU 在当前时间段空闲率。

      例如:

      • %Cpu0:使用了 3.1%,空闲了 80.9%。

      • %Cpu1:使用了 3.3%,空闲了 78.9%。

      • %Cpu2:使用了 2.3%,空闲了 80.5%。

      • 以此类推,所有 CPU 核心使用情况相对低,但总体看,系统每个核心空闲高(大部分在 78% 以上)。

      表明虽然负载高,但每个核心利用率相对低,可能意味着进程是 I/O 密集型进程数量多,导致 CPU 时间没有完全占用。

    分析总结

    • 负载:负载平均值非常高,尤其是 1 分钟负载( 17.48 )远超系统的 CPU 核心数。这可能意味着系统进程等待 CPU 时间,或 CPU 的某些操作(如 I/O 请求)导致阻塞。

    • CPU 空闲:虽然系统负载高,但每个核心空闲在 70%-80% 之间,说明 CPU 并未完全占用,可能是 I/O 或其他资源导致系统延迟。

    • 内存充足:内存使用量低(仅 1.3 GiB),并且交换空间使用,表明内存不是当前性能瓶颈。

    • 任务分布:大部分进程处于睡眠状态,可能等待某些 I/O 操作完成。 1 个运行任务说明当前活跃进程少,负载可能来自少数几个进程。


  • vmstat 命令

    主要关注 vmstat 命令输出cs ( context switches )属性值,启动进程后,日志如下:

    root@buildroot:~# vmstat 1
    procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
    r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
    0  0      0 1043028  17984  60580    0    0     0     0   78   90  0  0 100  0  0
    0  0      0 1043028  17984  60580    0    0     0     0   38   55  0  0 100  0  0
    0  0      0 1043028  17992  60580    0    0     0    12  109  133  0  0 99  0  0
    0  0      0 1043028  17992  60580    0    0     0     0   95  110  0  0 99  0  0
    
    # 执行 ./simulate_cpu_bottleneck 2 时刻
    19  0      0 1040764  17992  60580    0    0     0     0 262464 682330  3 72 25  0  0
    40  0      0 1040764  17992  60580    0    0     0     0 262257 668847  3 80 17  0  0
    53  0      0 1040764  17992  60580    0    0     0     0 253638 651784  2 83 16  0  0
    31  0      0 1040764  17992  60580    0    0     0     0 246351 636829  3 81 16  0  0
    42  0      0 1040764  17992  60580    0    0     0     0 254587 654205  2 82 16  0  0
    29  0      0 1040516  17992  60580    0    0     0     0 249660 643429  3 81 15  0  0
    

    以下详细分析:

    关键指标解释:

    • cs(Context Switches per second):每秒上下文切换次数。上下文切换指 CPU 从一个进程线程切换一个进程线程过程 。

    • in(Interrupts per second):每秒中断次数,包括时钟中断 。

    • us(User CPU time):用户态 CPU 使用率,表示用户进程占用 CPU 的时间百分比 。

    • sy(System CPU time):内核态 CPU 使用率,表示内核进程占用 CPU 的时间百分比 。

    • id(Idle CPU time): CPU 空闲时间,表示 CPU 未任何进程占用时间百分比 。

    上下文切换显著变化:

    • 初始状态

      • cs为 110 ,表示每秒发生 110 次上下文切换。

      • 系统整体运行平稳, CPU 空闲时间高(id 为 99%)。

    • 运行 simulate_cpu_bottleneck

      • cs显著增加,达到 682330 ,表示每秒发生 682330 次上下文切换。

      • in显著增加,达到 262464 ,表示每秒发生 262464 次中断。

      • CPU 使用率发生变化,us 为 3%,sy 为 72%,id 为 25%,表明系统态 CPU 使用率大幅增加,而用户态 CPU 使用率相对低。

    分析:

    1. 上下文切换增加原因

      • simulate_cpu_bottleneck 程序可能创建大量线程进程,并且这些线程进程频繁放弃 CPU(例如通过调用 sleep其他同步机制),导致操作系统频繁进行上下文切换 。

      • 高频率上下文切换增加内核态 CPU 使用率(sy),因为上下文切换主要内核完成 。

    2. 中断次数增加原因

      • 频繁上下文切换触发内核中断处理程序,用于管理线程切换调度 。

      • 这些中断主要软件中断(softirq),用于处理内核任务,如调度时间管理 。

    3. CPU 使用率变化原因

      • 高频率上下文切换导致内核态 CPU 使用率(sy)显著增加,而用户态 CPU 使用率(us)相对低 。

      • 程序可能主要内核执行任务,例如线程同步系统调用 。

    总结: 运行 simulate_cpu_bottleneck 程序后,vmstat 显示上下文切换次数(cs)和中断次数(in)显著增加,这表明程序触发大量上下文切换内核活动。这种行为由于程序创建大量线程,并且这些线程频繁放弃 CPU,导致操作系统频繁进行上下文切换 。


  • perf 命令

    上述 top 命令输出可以看到 simulate_cpu_bottleneck 的 PID 是 7321 ,可以通过 perf stat -p 7321 命令获取进程性能统计信息:

    root@buildroot:~# perf stat -p 7321
    
    Performance counter stats for process id '7321':
    
            214343.34 msec task-clock                       #    5.221 CPUs utilized
              14317887      context-switches                 #   66.799 K/sec
                  134      cpu-migrations                   #    0.625 /sec
                    0      page-faults                      #    0.000 /sec
          281409199909      cycles                           #    1.313 GHz
          118189146222      instructions                     #    0.42  insn per cycle
          15410712830      branches                         #   71.897 M/sec
            1651506356      branch-misses                    #   10.72% of all branches
    
          41.051394519 seconds time elapsed
    

    perf stat 输出来看,进程 7321simulate_context_switching)在运行期间表现以下特点:

    性能指标分析:

    • task-clock

      • 214343.34 msec:表示进程总共运行了 214.34 秒的 CPU 时间。

      • 5.221 CPUs utilized:表示平均有 5.221 个 CPU 核心进程占用。这表明进程核上并行运行,且 CPU 利用率高。

    • context-switches

      • 14317887:表示总共发生了 14317887 次上下文切换。

      • 66.799 K/sec:表示平均每秒发生 66799 次上下文切换。这是一个非常频率,表明线程频繁放弃 CPU,导致调度频繁切换线程。

    • cpu-migrations

      • 134:表示线程不同 CPU 核心之间迁移了 134 次。

      • 0.625 /sec:表示平均每秒发生 0.625 次 CPU 迁移。这个相对低,表明线程主要固定的 CPU 核心运行,没有频繁核心迁移。

    • page-faults

      • 0:表示没有发生页面错误。这表明程序内存访问非常高效,没有触发缺页中断。

    • cycles

      • 281409199909:表示总共发生了 281409199909 个 CPU 时钟周期。

      • 1.313 GHz:表示平均 CPU 时钟频率为 1.313 GHz。

    • instructions

      • 118189146222:表示总共执行了 118189146222 条指令。

      • 0.42 insn per cycle:表示平均每条指令需要 0.42 个时钟周期。这表明指令执行效率高,但优化空间。

    • branches

      • 15410712830:表示总共发生了 15410712830 次分支指令。

      • 71.897 M/sec:表示平均每秒发生 71897000 次分支指令。

    • branch-misses

      • 1651506356:表示总共发生了 1651506356 次分支预测失败。

      • 10.72% of all branches:表示分支预测失败率为 10.72%。这是一个相对比例,表明程序分支预测效率低。

    上述性能分析结果可以得出高频上下文切换原因 :

    • 线程频繁放弃 CPU

      • 程序每个线程频繁调用 usleep(1),这导致线程主动放弃 CPU,触发上下文切换。

      • 每次调用 usleep(1)使线程进入睡眠状态,调度器会切换其他线程运行。

    • 线程数量

      • 创建大量线程( 100 个),每个线程频繁放弃 CPU,导致调度需要频繁切换线程。

    高频率上文切换进而导致高 CPU 占用:

    • 频繁上下文切换

      • 每次上下文切换需要内核介入,这增加内核的 CPU 使用率(sy)。

      • 高频率上下文切换导致系统负载增加, CPU 占用率升高。

    • 线程任务简单

      • 每个线程任务简单(i * i),计算小,但线程数量多,导致整体 CPU 使用率高。


  • 优化策略

    实际工程情景中,如果遇到类似频繁上下文切换情况,在需要进行性能优化时,可以考虑以下策略:

    • 减少线程数量:减少线程进程数量,优化线程任务,或者调整线程调度策略,以减少上下文切换频率 。

    • 增加线程任务复杂性:优化线程任务,使线程时间片内完成工作,减少主动放弃 CPU 的次数,以减少上下文切换。

    • 调整线程调度策略:例如使用实时调度策略,减少上下文切换。

    • 使用线程池:使用线程池来复用线程资源,减少线程创建销毁开销。线程可以有效减少上下文切换次数。

中断处理过多模拟

执行 ./simulate_cpu_bottleneck 3 后,测试用例通过下面方式模拟中断处理过多导致 CPU 高负载情景:

1. 频繁信号触发

  • 定时器设置

    • setitimer 设置一个定时器,每 10us 触发一次 SIGALRM 信号。

    • 这种高频率信号触发模拟硬件设备频繁产生中断情况。

2. CPU 密集型中断处理

  • 信号处理函数

    • 每次信号触发时,handle_interrupt 函数调用。

    • handle_interrupt 函数中,执行一个简单计算任务(i * i),模拟 CPU 密集型中断处理工作。

    • 这种计算任务占用一定的 CPU 时间,导致 CPU 负载增加。

3. 阻塞等待信号

  • pause() 函数

    • simulate_hardware_interrupt 函数中,线程通过 pause() 函数进入阻塞状态,等待信号触发。

    • 每次信号触发后,线程阻塞状态唤醒,执行信号处理函数,然后再次进入阻塞状态。

可以通过下面工具监控系统状态。


  • top 命令

    执行 top 命令可以看到如下界面:

    High_Interrupts_simulation

    可以看到多个 CPU 均一定占用率。


  • vmstat 命令

    主要关注 vmstat 命令输出in ( interrupt )属性值,启动进程后,日志如下:

    root@buildroot:~# vmstat 1
    procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
    r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
    2  0      0 1066280   4232  53984    0    0     7     0 1796 2427 14 10 75  0  0
    0  0      0 1065808   4240  53976    0    0     0    12 9254 9351  1  2 97  0  0
    2  0      0 1066032   4240  53984    0    0     0     0 157572 155101  9 30 61  0  0
    0  0      0 1065776   4240  53984    0    0     0     0 115187 114196  6 22 71  0  0
    4  0      0 1066128   4240  53984    0    0     0    12 28050 27335  2  6 93  0  0
    3  0      0 1066192   4240  53984    0    0     0     0 179452 176975 10 34 56  0  0
    0  0      0 1066192   4240  53984    0    0     0     0 66883 65707  4 12 84  0  0
    2  0      0 1066128   4240  53984    0    0     0     0 89418 87806  5 16 78  0  0
    4  0      0 1066448   4240  53984    0    0     0     0 179625 176706 11 34 55  0  0
    0  0      0 1066352   4248  53984    0    0     0    12 5678 5793  0  1 98  0  0
    2  0      0 1065456   4248  53984    0    0     0     0 113790 111781  7 21 72  0  0
    0  0      0 1065680   4248  53984    0    0     0     0 162102 159638  8 32 60  0  0
    0  0      0 1065680   4248  53984    0    0     0     0   95  114  0  0 100  0  0
    

    可以看到 in 属性非常大,说明产生大量中断,进程模拟产生中断风暴。 而且,观察到,cs数值非常高。这通常系统负载高、任务调度频繁有关。


实际工程中,产生高频中断常见原因通常包括:

  • 高频网络数据包引发中断。

  • 高速磁盘操作产生中断。

  • 系统存在频繁触发定时器中断(例如高频硬件定时器)。

中断风暴可能性分析

  • in(中断次数)和 cs(上下文切换次数)值非常高,并且二者同步增长时,通常表示系统面临大量硬件中断。这些中断可能导致 CPU 在处理中断频繁进行上下文切换,从而引发 中断风暴

  • 中断风暴核心原因在于系统不断接收大量中断请求,迫使系统持续响应这些中断频繁切换任务。这种现象可能导致 CPU 过载,显著降低系统性能。

优化策略

针对高频中断导致性能问题,可以通过以下优化策略应对:

  • 检查系统哪些进程或硬件设备生成中断,并找出根源。

  • 优化硬件设备中断处理机制,尽量减少不必要中断触发。

  • 分析系统调度策略,优化进程调度任务处理方式,确保资源合理分配系统高效运行。

4.4.12.7. 参考文献