4.4.11. 系统性能优化指导
4.4.11.1. 概述
在嵌入式 Linux 系统中,性能优化是确保系统高效运行、满足实时性和资源约束的关键环节。嵌入式设备通常具有有限的硬件资源(如 CPU、内存和存储空间),因此需要通过软件优化来充分发挥硬件潜力,提升系统整体性能。优化不仅能够提高系统的响应速度和吞吐量,还能延长设备的使用寿命,降低功耗。
性能问题产生原因分析
在嵌入式 Linux 系统中,性能问题的产生可能由多种原因引起,以下是对性能优化问题产生原因的总结:
CPU 性能问题产生的原因
高负载任务过多
系统中运行了过多的高负载任务,导致 CPU 使用率接近 100%。例如,某些计算密集型任务(如数据处理、图像渲染)占用大量 CPU 时间。
解决方法:优化关键任务的代码,减少计算复杂度;使用多线程或多进程技术分散任务负载;调整进程优先级,确保关键任务优先运行。
上下文切换频繁
系统中存在大量线程或进程,频繁切换导致 CPU 时间浪费在上下文切换上,降低了实际处理任务的时间。
解决方法:减少不必要的线程和进程数量;优化线程同步机制,减少锁竞争;使用无锁编程技术。
中断处理过多
硬件中断频繁,导致 CPU 花费大量时间处理中断请求,影响正常任务的执行。例如,网络设备或磁盘设备的中断过多。
解决方法:优化硬件设备的中断处理机制,如调整中断触发方式(电平触发或边沿触发);使用中断合并技术减少中断频率。
内存性能问题产生的原因
内存不足
系统中运行了过多占用内存的任务,导致物理内存耗尽,频繁使用 swap 空间,降低系统性能。
解决方法:优化应用程序,减少不必要的内存分配;使用内存池技术管理动态内存;合理配置 swap 空间,避免过度依赖 swap;考虑更换更大容量的内存器件。
内存碎片
频繁的内存分配和释放导致内存碎片化,影响大块内存的分配效率。
解决方法:使用大页内存( Huge Pages)减少页表开销;优化内存分配策略,尽量减少小块内存分配。
缓存策略不合理
内核缓存策略(如文件缓存、磁盘缓存)配置不合理,导致缓存命中率低,增加磁盘 I/O 操作。
解决方法:调整内核缓存参数,如
vm.dirty_ratio和vm.dirty_background_ratio;优化文件系统缓存策略。
OOM(Out of Memory)问题
系统内存不足时, OOM Killer 随机杀死进程,导致系统不稳定。
解决方法:合理配置 OOM Killer 的行为,如调整
vm.overcommit_memory和vm.overcommit_ratio参数;监控内存使用情况,及时发现内存不足的问题。
磁盘性能问题产生的原因
I/O 阻塞
磁盘 I/O 操作频繁,导致系统等待 I/O 操作的时间过长。例如,大量文件读写操作或磁盘性能不足。
解决方法:优化文件系统,选择适合嵌入式设备的文件系统(如 F2FS、 JFFS2 );调整 I/O 调度算法(如 Deadline 或 CFQ);使用异步 I/O( AIO)技术减少阻塞。
文件系统碎片
文件系统使用时间过长,导致文件碎片化,影响文件读写速度。
解决方法:定期进行文件系统碎片整理;使用支持在线碎片整理的文件系统。
磁盘性能不足
磁盘设备性能不足,无法满足系统需求。例如,使用了低速的机械硬盘或闪存设备。
解决方法:升级磁盘设备,如使用 SSD 替代机械硬盘。
文件系统选择不当
使用的文件系统不适合嵌入式设备的使用场景,导致性能问题。例如,使用传统的 ext3 文件系统在闪存设备上可能导致频繁的擦写操作,降低性能。
解决方法:根据设备特点选择合适的文件系统,如 F2FS 适用于闪存设备, XFS 适用于大文件存储。
网络性能问题产生的原因
网络带宽不足
网络带宽有限,无法满足系统对网络数据传输的需求。例如,高并发的网络请求导致网络拥塞。
解决方法:升级网络设备,如使用更高带宽的网卡或交换机;优化网络拓扑结构,减少网络延迟。
TCP 参数配置不合理
TCP 参数(如
tcp_max_syn_backlog、tcp_tw_reuse)配置不合理,导致网络连接建立和释放效率低下。解决方法:调整 TCP 参数,优化网络连接性能;使用 TCP 快速打开( TFO)技术减少连接建立时间。
网络连接过多
系统中存在大量未关闭的网络连接,导致系统资源耗尽。例如,僵尸连接占用大量端口资源。
解决方法:调整系统最大文件句柄数(
ulimit -n);优化应用程序,及时关闭无用的网络连接。
中断处理问题
网络设备中断处理不当,导致网络数据包丢失或延迟增加。
解决方法:优化网络设备的中断处理机制,如调整中断触发方式;使用 RPS(接收队列缩放)和 RFS(接收流转向)技术提高多核 CPU 的网络处理能力。
系统配置问题产生的原因
内核配置不合理
内核中包含不必要的模块和功能,增加了系统启动时间和运行开销。
解决方法:裁剪内核,移除不必要的模块和功能;根据实际需求定制内核配置。
系统服务过多
系统中运行了过多不必要的服务,占用系统资源,影响系统性能。
解决方法:关闭不必要的系统服务和守护进程;优化系统服务的启动顺序和参数配置。
资源限制不合理
系统资源限制(如内存限制、文件句柄限制)设置不合理,导致应用程序无法正常运行。
解决方法:根据实际需求调整系统资源限制参数;监控资源使用情况,避免资源耗尽。
安全策略影响
安全策略(如 SELinux、防火墙规则)过于严格,导致系统性能下降。例如,防火墙规则限制了某些必要的网络连接。
解决方法:优化安全策略,确保不影响正常业务;定期检查安全策略的有效性,避免过度限制。
性能优化目标
最大化硬件资源利用率。
降低系统延迟,提高实时性。
减少内存占用和存储 I/O。
优化网络性能,确保稳定通信。
性能优化层次
性能优化可以从硬件、内核、应用和系统调优等多个层面进行。每个层面都有其独特的优化方法和工具,以下是优化的层次结构:
硬件优化:选择合适的硬件并合理配置硬件参数。
内核优化:裁剪内核、调整内核参数、优化调度策略等。
应用优化:优化应用程序代码、减少资源占用、提高并发性能。
系统调优:调整系统服务、优化网络和 I/O 性能。
性能优化的基本原则
需求驱动:优化工作应基于实际需求,明确性能瓶颈和优化目标。
最小化原则:在满足功能需求的前提下,尽量减少系统资源的占用。
分阶段优化:按照从硬件到软件、从系统到应用的顺序逐步优化,避免盲目调整。
测试与验证:优化后需通过严格的测试验证性能提升效果,确保系统稳定性。
4.4.11.2. 性能诊断工具
注意: 本章中所述的 mpstat 、pidstat、iostat、sar 命令依赖于 sysstat 软件包。因此,用户在使用这些命令之前需要在 Buildroot 中启用 sysstat 相关配置:
BR2_PACKAGE_SYSSTAT=y
然后,重新编译根文件系统,关于 Buildroot 的详细内容可以参考本手册中 使用 Buildroot 制作根文件系统 章节。
top
top 命令是 Linux 和类 Unix 系统中广泛使用的一个命令行工具,用于实时显示系统的资源使用情况,包括 CPU 使用率、内存使用、运行的进程等。它能为系统管理员提供一个动态的实时视图,帮助他们监控系统性能,查找高资源消耗的进程以及进行性能调优。
top 的原理
top 的原理基于定期调用操作系统内核提供的接口,收集系统资源使用情况的统计数据,并将这些数据动态地展示给用户。每当用户运行 top 命令时,它会执行以下操作:
内核接口调用:
top使用/proc文件系统中的信息(如/proc/stat、/proc/meminfo、/proc/loadavg和/proc/[pid]/stat等)来获取系统和进程的相关数据,如 CPU 的统计数据、上下文切换次数、中断次数等。数据刷新:
top默认每隔 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
关键字段说明:
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 优先级较高的虚拟机。
中断统计
intr:中断统计信息。4026141:总中断次数。其他数字表示不同中断类型的次数。
上下文切换
ctxt:上下文切换次数。5159099表示系统已经执行了 5159099 次上下文切换。
系统启动时间
btime:系统启动时间(以秒为单位)。0表示系统启动时间从 1970 年 1 月 1 日开始计算(因为设备上没有使能 RTC 时钟,系统每次启动都是从 1970 零时启动)。
进程信息
processes:系统启动以来创建的进程总数。3981表示系统启动以来创建了 3981 个进程。procs_running:当前运行的进程数。1表示当前有 1 个进程正在运行。procs_blocked:当前处于不可中断睡眠状态的进程数。0表示没有进程处于不可中断睡眠状态。
软中断统计
softirq:软中断统计信息。3450227:总软中断次数。其他数字表示不同类型的软中断次数。
/proc/loadavg 文件包含了系统的负载平均值,反映了系统的繁忙程度。以下是对提供的日志内容的详细说明:
root@buildroot:~# cat /proc/loadavg
0.00 0.02 0.00 1/199 3976
关键字段说明:
负载平均值
0.00: 1 分钟内的平均负载。0.02: 5 分钟内的平均负载。0.00: 15 分钟内的平均负载。
进程信息
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 是一个强大的系统监控工具,但它也有一些限制:
显示信息不够详细:
top默认展示的内容虽然包含了大部分关键信息,但某些特定的资源信息或深入的分析可能需要额外的命令或参数。例如,网络活动、磁盘 I/O 等信息需要配合其他命令(如
iostat、sar等)一起使用。
实时性和性能开销:
尽管
top是一个实时工具,但它每次刷新时会重新计算数据,这可能会给系统带来一定的性能开销,尤其是在进程数目非常多的情况下。对于高频次的数据刷新,
top的性能可能会有所下降。
可定制性较差:
top提供了基本的交互式操作和参数设置,但对于复杂的需求,可能需要进行较为繁琐的配置。比如,某些高级视图、图形界面的呈现、颜色配置等,需要在命令行模式下进行较多的手动配置。
界面较为简陋:
相较于一些现代的监控工具,
top的界面显得比较简洁,不适合进行深度的图形化分析。用户在使用时需要熟悉多种快捷键,以便在动态界面中有效切换和获取信息。
top周期的选定:CPU 的使用率受到周期的影响,在 CPU 繁忙时使用
top -d1和top -d5的结果差异是非常大的,周期越大,越接近实际平均负载。 考虑这样的一种极端场景,在 1s 的时间内,前 100ms 负载 100%,后 900ms CPU 全部 idle,以 1s 为周期,负载就是 10%,以 100ms 为周期,负载就出现了 100% 的情况,基于以上情况考虑,一般建议以 5s 作为top的周期 (top -d5)。需要特别注意的是,
top命令适用于长时间的负载检测,对于一次性负载检查 (top -n1),top实现中第一次top计算的周期是 200ms,以 200ms 周期计算出来的 CPU 使用率非常不准,会对整体分析产生误导。
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:切换粗体 / 反向显示(仅在x或y时有效)。
过滤和用户筛选:
u/U:按有效 / 任意用户过滤。o/O:按其他标准过滤。
显示设置:
n/#:设置显示的最大任务数。Ctrl+O:显示其他过滤条件。V:切换森林视图。v:隐藏 / 显示森林视图子项。
进程管理:
k:终止进程(需要输入 PID)。r:更改进程优先级(需要输入 PID 和新的 nice 值)。
更新时间间隔设置:
d或s:更改刷新间隔时间。
配置和退出:
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:进程 IDUSER:进程所有者PR:进程优先级NI:进程的 nice 值VIRT:进程占用的虚拟内存RES:进程占用的物理内存%CPU:进程占用的 CPU 百分比%MEM:进程占用的物理内存百分比TIME+:进程累计运行时间S:进程状态( S 表示睡眠, R 表示运行)COMMAND:进程启动的命令
htop 简介
当前系统中集成了 htop 命令,htop 是 top 命令的一个增强版本,提供了更为丰富的功能和用户友好的界面。与 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
pidstat 是 sysstat 工具集中的一个命令,专门用于监控进程的 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 压力较大。可以结合
vmstat的 b(等待资源的进程数)和 wa( I/O 等待所占的 CPU 时间百分比,超过 30% 时表示 I/O 压力大)参数进一步分析。
iowait 指标解释及常见误解
iowait 计算方法:
%iowait 是 %idle 的子集,用于表示 CPU 处于空闲状态时,是否存在未完成的磁盘 I/O 请求。具体计算方法如下:
如果 CPU 处于空闲状态(
idle),内核会检查:是否有本地磁盘 I/O 请求未完成。
是否有网络磁盘挂载操作。
如果满足任一条件,
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计数为 2user计数为 3nice计数为 0iowait计数为 1steal计数为 0idle计数为 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 的进程数量增加。理解这一点有助于准确判断系统性能瓶颈。
可以借助下面的图来理解:

从上图可以看出, 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定期查询这些统计信息,并将其以易读的格式展示给用户。
数据来源与计算方式:
内存统计:
内存的统计数据由内核管理,vmstat主要关注的是物理内存的使用情况,包括:free:空闲内存
buff:用于缓冲的内存
cache:用于文件缓存的内存
swap:交换分区的使用情况
这些数据反映了内存的分配、释放、以及缓存与交换空间的使用情况。
进程与 CPU 统计:
procs(进程状态):这部分显示了进程在系统中的状态,比如:
r:就绪队列中的进程数b:等待 I/O 的进程数w:进程睡眠等待 I/O 的数目
CPU 统计:包括 CPU 的使用情况:
us( user): 用户态时间sy( system): 系统态时间id( idle): 空闲时间wa( wait): 等待 I/O 的时间st( steal):虚拟化环境下,当前 CPU 时间被其他虚拟机偷取的时间
I/O 统计:
bi( blocks in):每秒从块设备读入的块数
bo( blocks out):每秒写入到块设备的块数
in( interrupts):每秒的硬中断数量
cs( context switches):每秒的上下文切换次数
交换空间:
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
周期性监控:通过指定
delay和count参数,可以周期性地输出系统状态信息。例如,每 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 命令主要从以下系统文件中获取信息:
/proc/meminfo:
这是最常见的文件,free命令读取的内存使用情况数据来自该文件。/proc/meminfo包含了系统内存的详细统计信息,包括总内存、已用内存、空闲内存、缓存、交换空间等信息。用户可以通过命令cat /proc/meminfo查看这些信息。/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
字段说明如下:
23:44:36:含义:采样时间点。表示采样开始的时间。
CPU:含义:表示这一行统计信息所对应的 CPU。
all表示统计的是所有 CPU 的综合情况。
%user:含义:用户态 CPU 使用率。表示 CPU 在用户态下运行的时间占总时间的百分比。
示例:
23:44:37:0.00%,表示在这一秒内, CPU 在用户态下几乎没有运行。23:44:38:0.12%,表示在这一秒内, CPU 在用户态下运行了 0.12% 的时间。
%nice:含义: nice 优先级较高的进程的 CPU 使用率。表示 CPU 在运行 nice 优先级较高的进程时所占用的时间百分比。
示例:
23:44:37:0.00%,表示在这一秒内,没有 nice 优先级较高的进程运行。23:44:38:0.00%,表示在这一秒内,没有 nice 优先级较高的进程运行。
%system:含义:内核态 CPU 使用率。表示 CPU 在内核态下运行的时间占总时间的百分比。
示例:
23:44:37:0.00%,表示在这一秒内, CPU 在内核态下几乎没有运行。23:44:38:0.50%,表示在这一秒内, CPU 在内核态下运行了 0.50% 的时间。
%iowait:含义: I/O 等待时间百分比。表示 CPU 在等待 I/O 操作完成时所占用的时间百分比。
示例:
23:44:37:0.00%,表示在这一秒内, CPU 没有等待 I/O 操作。23:44:38:0.00%,表示在这一秒内, CPU 没有等待 I/O 操作。
%steal:含义:被“窃取”的时间百分比。在虚拟化环境中,表示 CPU 时间被虚拟机监视器( Hypervisor)占用的时间百分比。
示例:
23:44:37:0.00%,表示在这一秒内,没有 CPU 时间被虚拟机监视器占用。23:44:38:0.00%,表示在这一秒内,没有 CPU 时间被虚拟机监视器占用。
%idle:含义: CPU 空闲时间百分比。表示 CPU 处于空闲状态的时间占总时间的百分比。
示例:
23:44:37:100.00%,表示在这一秒内, CPU 完全处于空闲状态。23:44:38:99.38%,表示在这一秒内, CPU 有 99.38% 的时间处于空闲状态。
Average::含义:表示所有采样时间点的平均值。
示例:
%user:0.04%,表示在采样期间, CPU 在用户态下的平均使用率为 0.04%。%system:0.17%,表示在采样期间, CPU 在内核态下的平均使用率为 0.17%。%idle:99.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
字段说明如下:
23:45:14:含义:采样时间点。表示采样开始的时间。
kbmemfree:含义:空闲的物理内存量(以千字节为单位)。
示例:
23:45:15:357972KB,表示在这一秒内,系统有 357972 KB 的物理内存处于空闲状态。
kbavail:含义:可用的物理内存量(以千字节为单位)。包括空闲内存和可以回收的缓存 / 缓冲区内存。
示例:
23:45:15:435880KB,表示在这一秒内,系统有 435880 KB 的物理内存可供使用。
kbmemused:含义:已使用的物理内存量(以千字节为单位)。
示例:
23:45:15:163824KB,表示在这一秒内,系统有 163824 KB 的物理内存被使用。
%memused:含义:物理内存使用率(百分比)。
示例:
23:45:15:12.24%,表示在这一秒内,系统有 12.24% 的物理内存被使用。
kbbuffers:含义:用作缓冲区的内存量(以千字节为单位)。
示例:
23:45:15:66128KB,表示在这一秒内,系统有 66128 KB 的内存被用作缓冲区。
kbcached:含义:用作缓存的内存量(以千字节为单位)。
示例:
23:45:15:688264KB,表示在这一秒内,系统有 688264 KB 的内存被用作缓存。
kbcommit:含义:系统为了保证当前运行的进程不会因为内存不足而失败,所承诺的最小内存量(以千字节为单位)。
示例:
23:45:15:828364KB,表示在这一秒内,系统承诺的最小内存量为 828364 KB。
%commit:含义:承诺的内存量占总内存(物理内存 + 交换空间)的比例(百分比)。
示例:
23:45:15:61.88%,表示在这一秒内,系统承诺的内存量占总内存的 61.88%。
kbactive:含义:活跃的内存量(以千字节为单位)。这些内存是当前正在使用的,不太可能被回收。
示例:
23:45:15:73900KB,表示在这一秒内,系统有 73900 KB 的活跃内存。
kbinact:含义:不活跃的内存量(以千字节为单位)。这些内存是当前未使用的,可能被回收用于其他用途。
示例:
23:45:15:691580KB,表示在这一秒内,系统有 691580 KB 的不活跃内存。
kbdirty:含义:脏的内存量(以千字节为单位)。这些内存包含尚未写入磁盘的数据。
示例:
23:45:15:4KB,表示在这一秒内,系统有 4 KB 的脏内存。
Average::含义:表示所有采样时间点的平均值。
示例:
kbmemfree:357972KB,表示在采样期间,平均空闲的物理内存量为 357972 KB。%memused:12.24%,表示在采样期间,物理内存的平均使用率为 12.24%。kbcommit:828364KB,表示在采样期间,系统承诺的最小内存量为 828364 KB。%commit:61.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
字段说明如下:
23:46:11:含义:采样时间点。表示采样开始的时间。
DEV:含义:磁盘设备的名称。例如
mmcblk0、mmcblk0boot0等。
tps:含义:每秒传输的 I/O 操作次数( transactions per second)。表示每秒磁盘完成的 I/O 操作总数。
示例:
23:46:13:mmcblk0的tps为1.00,表示在这一秒内,mmcblk0完成了 1 次 I/O 操作。
rkB/s:含义:每秒从磁盘读取的数据量(以千字节为单位)。
示例:
23:46:13:mmcblk0的rkB/s为0.00,表示在这一秒内,mmcblk0没有读取任何数据。
wkB/s:含义:每秒写入磁盘的数据量(以千字节为单位)。
示例:
23:46:13:mmcblk0的wkB/s为4.00,表示在这一秒内,mmcblk0写入了 4 KB 的数据。
dkB/s:含义:每秒丢弃的数据量(以千字节为单位)。通常用于表示丢弃的写操作。
示例:
23:46:13:mmcblk0的dkB/s为0.00,表示在这一秒内,mmcblk0没有丢弃任何数据。
areq-sz:含义:平均每次 I/O 操作的数据量(以千字节为单位)。
示例:
23:46:13:mmcblk0的areq-sz为4.00,表示在这一秒内,每次 I/O 操作的平均数据量为 4 KB。
aqu-sz:含义:磁盘请求队列的平均长度。
示例:
23:46:13:mmcblk0的aqu-sz为0.00,表示在这一秒内,磁盘请求队列的平均长度为 0 。
await:含义:从请求 I/O 操作到完成的平均时间(以毫秒为单位)。包括请求队列等待时间和 I/O 操作时间。
示例:
23:46:13:mmcblk0的await为2.00,表示在这一秒内, I/O 操作的平均等待时间为 2 毫秒。
%util:含义:磁盘 I/O 操作占用 CPU 的时间百分比。表示磁盘在采样期间的利用率。
示例:
23:46:13:mmcblk0的%util为1.00,表示在这一秒内,mmcblk0的利用率为 1%。
Average::含义:表示所有采样时间点的平均值。
示例:
tps:0.33,表示在采样期间,mmcblk0的平均 I/O 操作次数为 0.33 次 / 秒。wkB/s:1.33,表示在采样期间,mmcblk0的平均写入数据量为 1.33 KB/ 秒。await:2.00,表示在采样期间,mmcblk0的平均 I/O 等待时间为 2 毫秒。%util:0.33,表示在采样期间,mmcblk0的平均利用率为 0.33%。
从这个日志可以看出当前系统的磁盘 I/O 情况:
mmcblk0在采样期间的 I/O 活动非常低。大部分时间没有 I/O 操作(tps为 0 ),偶尔有一些写操作(wkB/s为 4 KB)。mmcblk0boot0和mmcblk0boot1在整个采样期间没有任何 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
字段说明如下:
23:46:45:含义:采样时间点。表示采样开始的时间。
IFACE:含义:网络接口的名称。例如
lo(本地回环接口)、eth0(以太网接口)、wlan0和wlan1(无线网络接口)。
rxpck/s:含义:每秒接收的数据包数量( received packets per second)。
示例:
23:46:47:eth0的rxpck/s为2.00,表示在这一秒内,eth0接收了 2 个数据包。
txpck/s:含义:每秒发送的数据包数量( transmitted packets per second)。
示例:
23:46:47:eth0的txpck/s为4.00,表示在这一秒内,eth0发送了 4 个数据包。
rxkB/s:含义:每秒接收的数据量(以千字节为单位)。
示例:
23:46:47:eth0的rxkB/s为0.12,表示在这一秒内,eth0接收了 0.12 KB 的数据。
txkB/s:含义:每秒发送的数据量(以千字节为单位)。
示例:
23:46:47:eth0的txkB/s为0.79,表示在这一秒内,eth0发送了 0.79 KB 的数据。
rxcmp/s:含义:每秒接收的压缩数据包数量。
示例:
23:46:47:eth0的rxcmp/s为0.00,表示在这一秒内,eth0没有接收任何压缩数据包。
txcmp/s:含义:每秒发送的压缩数据包数量。
示例:
23:46:47:eth0的txcmp/s为0.00,表示在这一秒内,eth0没有发送任何压缩数据包。
rxmcst/s:含义:每秒接收的多播数据包数量。
示例:
23:46:47:eth0的rxmcst/s为0.00,表示在这一秒内,eth0没有接收任何多播数据包。
%ifutil:含义:网络接口的利用率(百分比)。表示网络接口在采样期间的繁忙程度。
示例:
23:46:47:eth0的%ifutil为0.00,表示在这一秒内 ,eth0的利用率非常低。
Average::含义:表示所有采样时间点的平均值。
示例:
rxpck/s:eth0的平均值为1.00,表示在采样期间,eth0每秒平均接收 1 个数据包。txpck/s:eth0的平均值为2.33,表示在采样期间,eth0每秒平均发送 2.33 个数据包。rxkB/s:eth0的平均值为0.06,表示在采样期间,eth0每秒平均接收 0.06 KB 的数据。txkB/s:eth0的平均值为0.38,表示在采样期间,eth0每秒平均发送 0.38 KB 的数据。%ifutil:eth0的平均值为0.00,表示在采样期间,eth0的平均利用率非常低。
从这个日志可以看出当前系统的网络接口活动:
eth0在采样期间有一些网络活动,主要表现为发送数据包(txpck/s和txkB/s),但接收数据包较少(rxpck/s和rxkB/s)。lo(本地回环接口)和无线接口wlan0、wlan1在采样期间没有任何网络活动。网络接口的利用率(
%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
以下是对字段的详细说明:
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:7428和192.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:319和0.0.0.0:320:这两个端口监听所有 IP 地址,但未指定协议或目的地址,可能是某些特定的服务。
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
下面是字段的详细分析:
默认路由
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网络接口。
局域网路由
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.0到192.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
以下是每个字段的详细解释:
第一行 :
tcp 0 0 0.0.0.0:30431 0.0.0.0:* LISTENProto (协议):
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表示该端口处于监听状态,等待来自外部的连接。
第二行 :
tcp 0 0 0.0.0.0:23 0.0.0.0:* LISTENProto (协议):
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表示该端口处于监听状态,等待来自外部的连接。
第三行 :
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTENProto (协议):
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 官方文档 。
性能诊断工具使用总结
对常用的系统性能监控工具进行分类总结如下:
CPU 监控命令:
top:实时显示系统中各个进程的资源占用情况。vmstat:报告关于进程、内存、分页、块 I/O、陷阱和 CPU 活动的信息。mpstat:显示每个可用 CPU 使用情况的报告。pidstat:报告每个进程的 CPU 使用情况。uptime:提供系统整体的运行状态信息,包括 CPU 负载情况。sar:统计 CPU 的使用情况,也可以查看 CPU 平均负载。
内存监控命令:
free:显示系统中空闲和已使用的物理内存和交换空间。top:同上,也可以用来监控内存使用情况。pidstat:同上,也可以用来监控内存使用情况。vmstat:同上,也可以用来监控内存使用情况。sar:查看内存使用情况。
IO 性能:
iostat:报告 CPU 和输入 / 输出统计信息。vmstat:同上,也可以用来监控 IO 性能。sar:收集、报告和存储系统活动信息,包括 IO 性能。iozone:
网络性能:
iperf3:网络性能测试工具。netstat:显示网络连接、路由表、接口统计等信息。sar:统计各种网络信息。
其他性能分析工具介绍
国际知名的性能分析专家 Brendan Gregg(性能分析工具火焰图的发明人)总结了 Linux 系统下的性能分析工具:

这张图展示了 Linux 性能工具的生态系统,涵盖了从硬件到应用程序的各个层面。图中将工具分为几个主要类别:可观测性工具、静态性能工具、应用程序配置工具、系统调用接口工具、文件系统工具、调度器工具、虚拟内存工具、时钟源工具、设备驱动工具、固件工具、网络控制器工具、 I/O 控制器工具、 I/O 桥接工具、 CPU 工具、内存工具、 DRAM 工具、 GPU 工具、 I/O 工具、 FAN 工具和电源工具。
以下是对图中各个部分的简要介绍:
可观测性工具 这些工具用于在系统负载下观察系统状态。
文件系统:
lsof,pcstat,df -h,dmesg,mdadm,lvm,dmsetup,trace,pidstat -d磁盘:
iostat,iotop,strace交换空间:
lshw,lscsil,blockdev,swapon -s,smartctl,fdisk -l,/proc/swaps
静态性能工具 这些工具可以在系统空闲时观察系统状态。
BPF (Berkeley Packet Filter):
perf,ftrace,funccount,funclatency,stackcount,kprobe,uprobe,argdist,trace,profile文件系统:
ext4slower,ext4dist,btrfs*,xfs*,zfs*磁盘:
cachestat,dcsnoop,filetop,fileslower,mountsnoop
应用程序配置工具 这些工具用于配置和监控应用程序。
strace,perf trace,syncnoop,sysdig,opensnoop,statsnoop,ugc ucalls
系统调用接口工具 这些工具用于监控和分析系统调用。
套接字:
tcptop,tcplife,tcpconnect,tcpaccept,tcpconnlat,tcpretransTCP/UDP:
mysqld_glower,gethostlatencyIP:
ldd,ltrace以太网:
ifconfig,ethtool,ethtool -l,ipconfig设备驱动:
sar,perf,dstat,dmesg,journalctl,lsmod固件:
/sys/...,perf,dmesg,tiptop
文件系统工具
VFS (虚拟文件系统):
lsof,pcstat,df -h,dmesg,mdadm,lvm,dmsetup,trace,pidstat -d文件系统:
multipath,mdflush
调度器工具
cpupid,execsnoop,runlat,cpudist,offcputime,latencytop,schedtool
虚拟内存工具
mpstat,powertop,top,htop,ps,pidstat,vmstat,slabtop,free,/proc/meminfo
时钟源工具
memleak,oomkill,slabratetop,numactl
设备驱动工具
ss,tcpdump,ip,route,iptables,iptraf-ng,dmesg
固件工具
biosnoop,bpftrace,biosnoop,bitsize
网络控制器工具
lscpci,lsusb,ethtool,ifconfig
I/O 控制器工具
iostat,iotop,strace
I/O 桥接工具
nicstat,netstat,ip
CPU 工具
turbostat,rdmsr,cpuid,lscpu,llcstat,lstopo,capable
内存工具
intel_gpu_top,intel_gpu_time,intel_gpu_frequency,numactl,memstat,lstopo
DRAM 工具
dramstat,dmidecode
GPU 工具
intel_gpu,gputop,nvidia-smi
I/O 工具
iostat,iotop,strace
FAN 工具
sar -m,fan,dmidecode
电源工具
powertop
关于这些工具的详细介绍可以在 Brendan Gregg 的博客 Linux Performance 中查看。
4.4.11.3. 系统优化策略
CPU 优化
CPU 优化策略主要集中在以下几个方面:
进程优先级管理:通过合理调整进程的优先级,确保重要进程获得足够的 CPU 时间,避免低优先级进程影响系统性能。
减少上下文切换:通过优化任务和进程的管理,减少频繁的上下文切换,提升 CPU 使用效率。
CPU 亲和性优化:通过将关键进程绑定到特定的 CPU 核心上,减少 CPU 迁移,提高处理效率。
实时性优化:通过启用实时内核补丁和调整调度策略,减少任务切换延迟,确保实时任务的及时执行。
这些策略主要适用于需要高并发、低延迟和高性能计算的系统环境,特别是对于实时性要求较高的应用或多任务处理环境,能够显著提升 CPU 的性能和系统的整体响应能力。
调整进程优先级
命令:
nice和renice是用来调整进程优先级的命令。nice在启动进程时设置优先级,renice用于动态调整已在运行中的进程的优先级。目的:合理分配 CPU 时间。通过调整进程优先级,可以确保重要进程获得更多 CPU 时间,而不重要的进程可以让步,这有助于提升系统的整体响应性和性能。
适用场景:在多进程或多任务环境中,可能会出现某些进程需要比其他进程更多的 CPU 资源。通过调整优先级,可以避免低优先级的进程占用过多资源,影响高优先级进程的执行。
示例:
# 启动一个进程并设定较低的优先级(高 nice 值) nice -n 10 command # 修改已运行进程的优先级 renice -n -10 -p <pid>
减少上下文切换
上下文切换:是指 CPU 在多个进程或线程之间切换时,保存和加载其执行状态(即上下文)的过程。频繁的上下文切换会增加 CPU 的负担,并导致性能下降。
策略:
合并过多的小任务:如果系统中有大量的小任务(如频繁的线程创建和销毁),它们会导致大量的上下文切换。通过调整线程池大小、合并任务等方式,可以减少上下文切换的频率。
检查
pid_max和进程数限制:pid_max参数控制最大进程数,如果系统进程数过多,可能会导致频繁的调度和管理,浪费 CPU 资源。适当限制进程数,避免过多的无用进程占用资源,可以减少上下文切换。
适用场景:在多任务并发环境中,过多的小任务或进程会导致频繁上下文切换,从而降低整体性能。减少无用的进程和任务,有助于提升系统响应速度和资源使用效率。
CPU 亲和性
定义与工作原理:
CPU 亲和性(CPU Affinity):指将某一进程或线程绑定到特定的 CPU 或 CPU 集合上,使得该进程或线程仅在指定的 CPU 上运行。这样做的主要目的是提高进程的运行效率。
原理:进程在运行时会在 CPU 缓存中保留一定的残余信息。如果下一次运行该进程时,能够在同一 CPU 上执行,就能利用这些缓存信息,避免缓存未命中的情况,从而减少 CPU 处理的负担,提升性能。
软亲和性与硬亲和性:
软亲和性:操作系统调度器(如 Linux 调度器)会自动倾向于让进程保持在同一个 CPU 上运行,而不频繁迁移。这样可以减少进程在多个 CPU 之间的切换,降低资源消耗,提高系统整体性能。
硬亲和性:用户可以通过系统 API 手动指定进程运行在哪个 CPU 上,从而满足特定的性能需求。例如,在多核系统中,某些进程可以被固定在特定的核心上运行,避免调度器的干预。
系统的默认调度与优化:
一般情况下, Linux 系统的调度器已经具备优化能力,默认的调度策略能够平衡负载和性能,适用于大多数应用程序。
然而,针对特定应用,尤其是对性能要求极高的任务,系统的通用调度策略可能不能达到最佳效果。这时,通过使用 CPU 亲和性,用户可以手动优化特定进程的运行效率。
命令
taskset的应用:命令:
taskset是 Linux 系统中的一个命令,用于将进程绑定到特定的 CPU 核心上,从而避免进程在多个 CPU 核心之间频繁迁移(即“ CPU 迁移”)。通过这一方法,可以显著减少由于频繁迁移导致的缓存失效和调度开销。目的:通过固定进程到特定的核心上运行,减少 CPU 核心间的迁移,避免调度开销,提高计算效率。
适用场景:对于性能要求较高的任务,特别是需要高频繁计算的进程,可以使用
taskset命令将进程绑定到特定 CPU 核心,从而避免多核调度时产生的性能损耗。示例:
# 将进程绑定到第一个 CPU 核心上 taskset -c 0 <command>
应用场景:
高密度计算进程:对于一些计算密集型进程,如果不希望其在多个 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 操作,清理无用数据块,保持闪存的高效性能。
文件系统选择
适合闪存的文件系统:
UBIFS 和 F2FS 是为闪存设备(如 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 闪存设备,推荐使用 noop 或 kyber 调度器。这些调度器比较简单,并且在闪存设备上能减少不必要的延迟。
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以及kyberI/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(因为它被方括号 [ ] 包裹起来了),当前系统还支持kyber和none两种 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 功能。
网络优化
网络优化策略主要围绕三个方面:
TCP 连接的优化:通过调整端口范围和启用 TIME_WAIT 回收,提高网络连接的复用性和端口的可用性,特别适用于高并发场景。
多核 CPU 网络吞吐量优化:通过启用 RSS 和 IRQ 绑定,提升网卡接收数据包的处理能力,减少 CPU 瓶颈。
资源限制优化:通过调整
nofile和nproc限制,确保系统能够处理更多的并发连接和进程,适用于高负载、高并发的服务器环境。
这些优化方案在高并发、高吞吐量的网络服务中尤为重要,能够显著提升系统性能和稳定性。
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 利用率,防止某个核心的过度负载。
连接数限制
调整
nofile和nproc限制:命令:对于嵌入式 Linxu 系统可以通过修改
/etc/profile文件来调整nofile(文件描述符)和nproc(进程数)限制。目的:
nofile:限制系统中每个进程可以打开的文件描述符的数量,增加该限制可以允许更多的并发连接或文件操作。
nproc:限制系统中每个用户可以创建的最大进程数,增大此限制能够允许用户启动更多的进程,适用于需要启动大量子进程的场景。
适用场景:高并发服务,特别是需要大量并发连接的网络应用(如 Web 服务器、数据库连接池、大规模分布式应用等)。
配置示例:
sudo vi /etc/profile # 添加下面内容 ulimit -n 65536 # 设置最大文件描述符数 ulimit -u 65536 # 设置最大进程数
4.4.11.4. 应用优化
在应用编码层的优化策略,主要聚焦于性能提升和内存管理方面。
Coding 原则
避免巨量函数调用(核心循环中尽量使用 inline 函数)
策略分析:函数调用会引入一定的开销,尤其是在核心循环中频繁调用时。使用
inline函数可以在编译时将函数代码直接嵌入调用处,从而减少函数调用的开销,提升性能。对于性能要求高的代码段,尤其是循环中频繁执行的函数,使用inline可以显著提高效率。注意:过度使用
inline可能导致代码膨胀,尤其是函数体较大的情况下,因为每次调用都会将代码复制到调用点,可能增加二进制文件的体积。
循环无关代码外提
策略分析:循环内的代码应尽量只包含循环所必需的计算,避免在每次迭代中执行不相关的计算。循环外提代码是指将那些不依赖于循环变量且每次迭代都重复执行的操作移出循环,从而减少冗余的计算。这样可以有效提升程序性能,尤其是在循环次数较多时。
避免不必要的内存引用操作
策略分析:内存访问操作通常是比较耗时的,尤其是对于高延迟的内存访问(如从磁盘读取数据、访问远程内存等)。优化内存引用意味着减少不必要的数据访问或重复访问相同数据。通过合理的缓存和内存管理,可以减少内存带宽的消耗,提高数据处理速度。
守护线程优化
守护线程优化的目标是通过减少数量和简化代码来降低资源占用,提升系统性能和稳定性。优化后的守护线程能够减少内存使用,并避免资源管理瓶颈。
核心策略是 减少守护线程数量,简化代码:
策略分析:
守护线程在后台运行,通常不参与主业务逻辑,因此不应占用过多资源。线程越多,占用的系统资源越大。
代码复杂度高的守护线程会增加计算、内存分配和管理开销,进而影响性能。
为避免性能瓶颈,应减少守护线程数量并优化代码,以减少内存占用,减轻系统调度和资源管理压力,提升整体性能。
风险点:
长时间运行的守护线程可能引发内存泄漏,因其内存分配和释放不易察觉,导致内存占用无法释放。
在高并发或长时间运行的系统中,内存泄漏可能快速累积,降低性能,甚至崩溃。
因此,需要定期检查和清理守护线程资源,避免内存泄漏,确保系统稳定运行。
动态库加载优化
动态库加载优化策略主要是减少动态库的加载数量,从而优化程序的启动时间、内存占用和运行时性能。
减少无用动态库的加载
策略分析:去掉不必要的动态库。通过减少不必要的库,程序启动时的开销和内存占用都会减少。这是一个非常直接有效的优化方式。
影响:去除不必要的库后,程序加载的库会减少,进程的内存占用、加载时间和符号查找等都能够得到优化,减少了不必要的工作。
重新组织动态库的结构
策略分析:通过重新组织库结构来减少加载的动态库数量,目的是避免多个库之间的冗余加载。每个库应该只加载必须的部分,避免过多的库相互依赖。
影响:这个方法有助于提升效率,减少了加载的库数量,进而减少了符号查找、动态链接等运行时开销。
将动态库编译为静态库
优点:
减少了加载动态库的数量,因为静态库在编译时就被合并到可执行文件中,不再需要在程序运行时加载。
动态库与其他库合并后,内部函数调用不再需要符号查找、动态链接,避免了这些开销。
缺点:
占用更多内存:当静态库被多个进程或其他库依赖时,它会被复制多份,导致内存占用增加。由于静态库直接嵌入程序中,不能像动态库那样共享内存中的代码段。
影响性能:每个进程都加载自己的静态库副本,导致内存的浪费。同时,由于静态库增加了进程的内存需求,可能导致
page fault增多,从而影响程序的加载速度和运行效率。
适用情况:当某些动态库仅被少数进程使用时,编译为静态库可以减少启动时的加载开销。然而,对于常驻守护进程的动态库,静态库反而不如动态库高效。
使用 dlopen 动态加载动态库
优点:
精确控制动态库的生命周期:
dlopen使得程序能够按需加载动态库,而不是在程序启动时就加载所有依赖的库。这可以减少启动时间,并且根据需要动态管理库的加载和卸载。减少内存使用:通过
dlopen动态加载库,可以在不使用时卸载库,减少内存中未使用的部分。对于一些不常用的库,这样的按需加载会节省内存。
影响:
使用
dlopen可能增加程序的复杂性,因为它需要手动管理库的加载和卸载。这意味着开发者必须保证在不再需要库时及时调用dlclose,以避免内存泄漏或其他资源问题。此外,
dlopen可能增加额外的性能开销,尤其是在进行符号解析时。如果没有优化得当,可能导致性能下降。
4.4.11.5. USE 方法介绍
USE 方法的核心内容
USE 方法( Utilization Saturation and Errors Method)是国际知名的性能分析专家 Brendan Gregg(性能分析工具火焰图的发明人)提出的一种用于系统性能分析的高效方法论,旨在快速识别和解决系统资源瓶颈。
USE 方法的核心是通过检查系统的每个资源的 利用率( Utilization)、饱和度( Saturation)和 错误率( Errors)来快速定位性能问题。这种方法论的目的是在性能调查的早期阶段,快速识别系统性的瓶颈。
它通过以下三个关键指标来分析系统资源:
Utilization(利用率):
资源忙于处理工作的时间百分比。
例如, CPU 使用率、磁盘 I/O 使用率。
Saturation(饱和度):
资源因过载而排队等待的程度(资源超出其服务能力的额外工作量,通常表现为队列长度)。
例如, CPU 运行队列长度、磁盘 I/O 等待队列。
Errors(错误率):
资源发生的错误数量或频率。
例如,网络丢包、磁盘 I/O 错误。
USE 方法适用于下面场景:
系统性能调优。
容量规划和资源分配。
故障排查和根因分析。
USE 方法具有下面优势:
快速定位问题:通过简单的指标快速识别性能瓶颈。
全面覆盖:适用于硬件和软件资源,覆盖系统各个层面。
易于实施:只需检查三个指标,适合所有用户群体。
USE 方法流程说明
列出所有资源:
包括 CPU、内存、磁盘、网络等硬件资源,以及软件资源(如线程池、连接池)。
检查每个资源的
USE指标:对每个资源,依次检查其利用率、饱和度和错误。
识别瓶颈:
根据
USE指标,快速定位性能瓶颈。
深入分析:
针对瓶颈资源,使用更详细的工具和方法进行深入分析。
USE 方法的具体流程如下:

下面是对流程图中各个步骤的详细解释:
开始(Start):
流程从这里开始,准备进行性能分析。
识别资源(Identify Resources):
确定需要检查的系统资源,包括 CPU、内存、磁盘、网络等硬件资源,以及线程池、连接池等软件资源。
选择资源(Choose a Resource):
从识别出的资源列表中选择一个资源进行分析。
错误存在吗?(Errors Present?):
检查选定资源是否存在错误。如果存在错误( Y),则进行下一步的错误调查。
如果没有错误( N),则继续检查该资源的利用率。
高利用率?(High Utilization?):
检查选定资源的利用率是否过高。如果利用率高( Y),则可能存在性能瓶颈,需要进一步调查。
如果利用率不高( N),则继续检查资源的饱和度。
饱和度?(Saturation?):
检查选定资源是否存在饱和度问题。如果存在饱和度( Y),则表明资源可能无法处理更多的工作负载,需要进一步调查。
如果没有饱和度( N),则继续检查下一个资源。
所有资源都检查完毕?(All Resources Fully Checked?):
检查是否所有资源都已检查。如果所有资源都已检查( Y),则流程结束。
如果还有资源未检查( N),则返回步骤 3 ,继续选择下一个资源进行检查。
识别问题(Identified the Problem?):
在调查过程中,检查是否已经识别出问题。如果已经识别出问题( Y),则返回步骤 3 ,继续检查其他资源或结束流程。
如果尚未识别出问题( N),则继续进行调查和发现( Investigate Discovery)。
调查和发现(Investigate Discovery):
如果在前面的步骤中发现了问题,但尚未识别出问题的根本原因,则进行更深入的调查和发现,以确定问题的根本原因。
结束(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 1、sar -u、dstat -c等命令。内存利用率:使用
free -m、vmstat 1、sar -r、dstat -m等命令。网络接口利用率:使用
sar -n DEV 1、ip -s link、/proc/net/dev等命令。存储设备 I/O 利用率:使用
iostat -xz 1、sar -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 系统时,可以按照以下步骤操作:
确定监控目标:首先,明确需要监控的系统资源,如 CPU、内存、磁盘和网络等。
选择适当的工具:根据监控目标,从文章中提供的指标列表中选择合适的命令行工具。例如,可以使用
vmstat来监控 CPU 利用率,使用iostat来监控磁盘 I/O 利用率,使用sar来监控网络接口利用率等。收集性能数据:运行选定的工具并收集性能数据。例如,要检查 CPU 利用率,可以使用以下命令:
vmstat 1:显示每秒的 CPU 和系统资源使用情况。mpstat -P ALL 1:显示所有 CPU 的使用情况。top或htop:显示进程级别的 CPU 使用情况。pidstat 1:显示每个进程的 CPU 使用情况。
分析性能数据:分析收集到的数据,识别利用率( Utilization)、饱和度( Saturation)和错误( Errors)。例如,可以检查
vmstat输出中的“ r”值是否大于 CPU 核心数,这可能表明 CPU 饱和。识别瓶颈和错误:通过分析,识别系统性能的瓶颈和错误。例如,如果发现 CPU 利用率过高,可能需要进一步调查是否有进程占用了过多的 CPU 资源。
采取行动:根据分析结果,采取相应的优化措施。这可能包括调整系统配置、优化应用程序或升级硬件资源。
定期监控:将性能监控作为常规维护的一部分,定期检查系统性能,以确保及时发现并解决潜在问题。
深入分析和延迟分析:如果完成这个检查表后仍然遇到性能问题,可以继续使用其他策略,如深入分析和延迟分析。
4.4.11.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命令后可以看到如下界面:
分析其中的关键输出:
%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 没有空闲时间,完全在忙碌地处理任务。
综上可以看出:
CPU 总体使用情况:
系统总的
12.47%CPU 时间用于用户空间任务,87.53%时间空闲,说明系统负载较轻,大部分时间 CPU 没有被充分利用。
各个核心的分布情况:
核心 3 的负载非常高,几乎 100% 的时间都在处理用户进程。其他核心(如核心 0 到 2 、 4 到 7 )几乎处于空闲状态,这可能表明某个特定任务或进程集中在核心 3 上运行。
没有 I/O 或中断等待:
iowait、irq和softirq都是 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值,表示大量的用户态和内核态计算。top或htop中某个进程占用了大量的 CPU 资源。iowait和idle时间较低,表明 CPU 大量处于活跃状态,较少有空闲时间。
在实际的工程情景中,如果遇到类似的情况需要进行性能优化,可以考虑以下策略:
减少计算复杂度:分析高负载任务的代码逻辑,寻找可以优化的算法或数据结构,减少不必要的计算。
并行化任务:将任务分解为多个子任务,并行执行以充分利用多核 CPU 的优势。例如,使用多线程或异步编程模型。
上下文切换频繁模拟
执行 ./simulate_cpu_bottleneck 2 后,将模拟一个频繁地触发上下文切换的情景,上下文切换通常发生在以下几种情况:
时间片用完:线程运行了一段时间后,时间片用完,操作系统会切换到其他线程。
等待资源:线程主动调用 sleep 或等待 I/O 操作,操作系统会切换到其他线程。
线程间同步:线程之间通过锁或其他同步机制进行通信,导致线程阻塞和切换。
为了实现高频率的上下文切换,设计的测试用例中包含了多个线程,每个线程执行简单的任务,并且频繁地调用 sleep 来模拟线程间的同步以产生大量的上下文切换。
可以通过下面工具查看上下文的切换状态。
top命令执行
top命令后可以看到如下界面:
以下是对系统当前状态的分析:
CPU 使用情况 系统有 8 个 CPU 核心,分别是
Cpu0到Cpu7。每个核心的使用情况如下:%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 使用率相对较低。
分析:
上下文切换增加的原因:
simulate_cpu_bottleneck程序可能创建了大量线程或进程,并且这些线程或进程频繁地放弃 CPU(例如通过调用sleep或其他同步机制),导致操作系统频繁地进行上下文切换 。高频率的上下文切换会增加内核态 CPU 使用率(
sy),因为上下文切换主要由内核完成 。
中断次数增加的原因:
频繁的上下文切换会触发内核中的中断处理程序,用于管理线程的切换和调度 。
这些中断主要是软件中断(
softirq),用于处理内核任务,如调度和时间管理 。
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输出来看,进程7321(simulate_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命令后可以看到如下界面:
可以看到多个 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 过载,显著降低系统性能。
优化策略:
针对高频中断导致的性能问题,可以通过以下优化策略来应对:
检查系统中哪些进程或硬件设备生成了过多的中断,并找出根源。
优化硬件设备的中断处理机制,尽量减少不必要的中断触发。
分析系统的调度策略,优化进程调度和任务处理方式,确保资源的合理分配和系统的高效运行。