目录
我们承担ROS,FastDDS等中间件以及Linux,C++,cmake等技术的项目开发和专业指导和培训,有10年+工作经验,质量有保证,如有需要请私信联系。
工具集
性能分析工具
uptime
$ uptime
19:49:31 up 36 days, 5:25, 1 user, load average: 0.52, 0.11, 0.04
当前时间 系统运行时间 正在登陆的用户数 1min 5min 15min的平均负载
vmstat:
- cs(context switch):每秒上下文切换的次数
- in(interrupt):每秒中断的次数
- r(running or runnable):就绪队列长度,也就是正在运行和等待的CPU的进程数
- b(blocked):不可中断睡眠状态的进程数
- us:用户进程CPU使用率
- sy:系统进程CPU使用率
pidstat
pidstat是一个非常实用的系统性能工具,可以用来监控单个任务的cpu,每个任务用户态,内核态的cpu占用,内存,I/O等使用情况。pidstat是sysstat工具包的一部分。
pidstat可以看到每个进程的上下文切换的详细情况。
-
命令行参数
- 没有命令行参数,显示所有进程的cpu使用情况
pid -p [pid]
: 显示指定进程的cpu使用情况pidstat -r
: 显示所有进程的内存使用情况pidstat -r -p [pid]
: 显示指定继承的内存使用情况pidstat -d
: 显示所有进程的i/o使用情况pidstat -d -p [pid]
: 显示特定进程的io使用情况- 持续监控进程的cpu使用情况,每隔5s更新一次:
pidstat 5
- 持续监控某个进程的cpu使用情况,每个5s更新一次:
pidstat -p [pid] 5
,持续监控的最后部分还有average部分,用来计算5组数据的平均值 - 默认显示进程的指标数据,加上 -t 之后才会输出线程的指标
-
输出内容
- %usr:用户态cpu使用率
- %system:内核态cpu使用率
- %guest:运行虚拟机cpu使用率
- %wait:等待cpu使用率
- %cpu:总的cpu使用率
- cswch:每秒自愿上下文切换的次数
- nvcswch:每秒非自愿上下文切换的次数
perf
perf是性能分析工具,(运行perf需要管理员权限)收集各种类型的性能数据:
- perf stat:这个命令可以收集和显示统计信息,包括CPU周期,缓存引用计数等;如perf stat ls, 会运行ls命令,并显示其性能统计信息
- perf top:类似于top,能实时显示占用cpu时钟最多的函数或指令,因此可以用来查找热点函数,时展示了系统的性能信息,但它的缺点是并不保存数据,也就无法用于离线或者后续的分析
hello@gf:~$ sudo perf top
Samples: 4M of event 'cycles', 4000 Hz, Event count (approx.): 25589544241 lost: 0/0 drop: 0/0
Overhead Shared Object Symbol
0.14% [kernel] [k] pty_write
0.14% node [.] v8::internal::(anonymous namespace)::Invoke
0.14% libc.so.6 [.] cfree@GLIBC_2.2.5
0.14% perf [.] sort__sym_cmp
0.14% node [.] v8::internal::GlobalBackingStoreRegistry::Unregister
0.14% node [.] Builtins_KeyedLoadIC_Megamorphic
0.14% [kernel] [k] __cond_resched
0.14% mem_test [.] tts
For a higher level overview, try: perf top --sort comm,dso
输出结果中,第一行包含三个数据:采样数Samples,事件类型event,事件总数量Event count;
每行中,
第一列:Overhead:该符号的性能事件在所有采样中的比例
第二列Shared Object:该函数或指令所在的动态共享对象,如内核,进程名,动态库,内核模块等
第三列Object:动态共享对象的类型,[.] 表示用户空间的可执行程序或动态库,[k]表示内核空间
第四列Symbol:符号名/函数名,当函数名未知时,用十六进制的地址来表示
- perf record:记录程序的性能事件供后续分析,会在当前目录下创建一个名为perf.data文件,包含收集的性能数据,需要用 perf report -i 解析展示
- perf list:这个命令会列出所有可用事件
以上命令中,可以加上-g参数,开启调用关系的采样,方便根据调用链来分析性能问题。
CPU性能指标
CPU使用率
CPU使用率描述了非空闲时间占总CPU时间的百分比,根据cpu上运行任务的不同,又分为用户cpu,系统cpu,等待I/O cpu,软中断,硬中断等。
-
用户cpu使用率:包括用户态cpu使用率(user)和低优先级用户态cpu使用率(nice),表示cpu在用户态运行的时间百分比。用户态cpu使用率高,说明有应用程序比较繁忙
-
系统cpu使用率:表示cpu在内核态运行的时间百分比
-
等待I/O的cpu使用率:也成为iowait,表示等待I/O的时间百分比。iowait高,说明系统和硬件设备的io交互时间较长
-
软中断与硬中断的cpu使用率:使用率高说明系统发生了大量的中断
- /proc 虚拟文件系统,向用户空间提供了系统内部状态的信息,/proc/stat 提供的是系统的CPU和任务统计信息,可以通过命令
cat /proc/stat | grep ^cpu
查看cpu的信息 - /proc/[pid]/stat 这个文件包含了每个进程的cpu信息
平均负载
单位时间内,系统处于可运行状态和不可中断状态的平均进程数,也就是平均活跃进程数。和CPU的使用率并没有直接关系
平均负载的计算方式为:通过对过去的负载进行指数衰减平均得到,涉及到一些比较复杂的算法。
- 可运行状态:正在使用或者正在等待使用CPU的进程,使用ps命令看到的处于R状态的进程
- 不可中断状态是ps总看到的D状态
平均负载多少较为合理?
首先,平均负载最理想的情况是等于CPU个数。所以在评判平均负载时,首先需要知道系统有几个CPU,可以通过文件 /proc/cpuinfo中读取:grep 'model name' /proc/cpuinfo | wc -l
;有了CPU个数,就可以判断出,当平均负载比CPU个数还大的时候,系统已经出现了过载。
在实际环境中,当平均负载高于CPU个数的70%的时候(经验值),可能就是平均负载过高了,就需要排查分析原因了。
当然70%并不是绝对的,最推荐的方式,就是把系统的平均负载监控起来,然后根据更多的历史数据来判断负载的变化趋势,当发现负载有明显升高的趋势时,再做分析和调查。
平均负载和CPU使用率,这两个概念容易混淆,现做以下区分:
- CPU密集型进程:使用大量CPU会导致平均负载升高,此时两者是一致的;
- I/O密集型进程:等待I/O会导致平均负载升高,但CPU使用率不一定高
- 大量等待CPU的进程调度会导致平均负载升高,此时CPU使用率也会比较高
上下文切换
上下文切换是保证Linux正常运行的一项功能,但过多的上下文切换会成为cpu性能瓶颈
- CPU寄存器中存储当前和即将执行的指令,被称作CPU上下文,CPU的上下文切换就是将前一个任务的CPU上下文保存起来,然后加载新任务的上下文到这些寄存器和程序计数器当中,然后再跳转到程序计数器所指的新位置运行新任务。
- CPU的上下文切换包括进程上下文切换,线程上下文切换,中断上下文切换
- 自愿上下文切换:进程无法获取所需资源导致的上下文切换,如I/O,内存等系统资源不足时,就会发生自愿上下文切换
- 非自愿上下文切换:进程由于时间已到等原因,被系统强制调度,进而发生的上下文切换,如,大量进程都在争抢CPU时就容易发生非自愿上下文切换
CPU缓存的命令率
CPU性能排查
- 通过vmstat查看正在运行和等待CPU的进程数,查看上下文切换次数
- 通过pidstat查看是哪个进程导致CPU使用率过高,和上下文切换,通过-t查看每个线程
- 通过查看/proc/interrupts 查看中断次数的增加原因
- 找到进程:通过top,ps,pidstat等工具的使用,可以找到cpu使用率过高的进程
- 找到函数:perf
CPU优化
应用程序优化
- 编译器优化,如gcc打开优化选项 -O2等
- 算法优化,使用复杂度更低的算法,如在数据较大的情况下可以用O(nlogn)的排序算法代替O(n^2)的排序算法
- 异步处理:避免程序因为等待某个资源而一直阻塞,从而提升程序的并发处理能力,如把轮询替换为事件通知等
- 多线程代替多进程,相比于进程的上下文切换,线程的上下文切换不切换进程地址空间,因此可以降低上下文切换的成本
- 善用缓存
- 代码优化,代码中不合理的地方,如频繁的线程创建销毁使用线程池,频繁的内存申请释放采用内存池,懒初始化,函数内联,内存对齐等
系统优化
- CPU绑定:把进程绑定到一个或多个核上,可以提高cpu缓存的命中率,减少跨cpu调度带来的上下文切换问题
- cpu独占:跟cpu绑定类似,进一步将cpu分组,并通过cpu亲和性机制为其分配进程
- 优先级调整:使用nice调整进程的优先级。适当降低非核心应用的优先级,增高核心应用的优先级,可以确保核心应用程序得到优先处理
- 为进程设置资源限制:使用linux cgroups 来设置进程的cpu使用上限,可以防止由于某个应用自身的问题而耗尽系统资源
- NUMA优化:支持 NUMA 的处理器会被划分为多个 node,每个 node 都有自己的本地内存空间。NUMA 优化,其实就是让 CPU 尽可能只访问本地内存。
- 中断负载均衡:无论是软中断还是硬中断,它们的中断处理程序都可能会耗费大量的 CPU。开启 irqbalance 服务或者配置 smp_affinity,就可以把中断处理过程自动负载均衡到多个 CPU 上。
避免过早优化
过早优化是万恶之源
因为,一方面,优化会带来复杂性的提升,降低可维护性;另一方面,需求不是一成不变的。针对当前情况进行的优化,很可能并不适应快速变化的新需求。这样,在新需求出现时,这些复杂的优化,反而可能阻碍新功能的开发。所以,根据性能评估再进行优化。
压力测试工具
stress
Linux系统压力测试工具
cpu密集型:stress --cpu 1 --timeout 6000
io密集型:stress -i 1 --timeout 600
sysbench
sysbench是一个模块化、跨平台和多线程的基准测试工具,主要用于评估和测试各种系统参数,如CPU性能,磁盘I/O性能,内存分配和传输速率,POSIX线程,数据库负载性能等。
Sysbench的主要功能和用途如下:
- CPU性能测试:通过执行特定的计算任务,例如计算素数,来评估CPU的性能。
- 文件I/O性能测试:评估文件系统的性能,包括文件的创建,读写,重写,删除等。
- 内存性能测试:评估内存操作的性能,如分配内存以及内存读写速度。
- 线程和同步性能测试:测试多线程环境下的锁和互斥锁的性能。
- 数据库性能测试:对MySQL, PostgreSQL, Oracle等数据库进行读写和查询的性能测试。
sysbench是一款非常强大的系统性能基准测试工具,它在性能测试和性能调优,服务器配置,硬件评估等场景都有广泛的应用。
示例:
# 以10个线程运行5分钟的基准测试,模拟多线程切换的问题
$ sysbench --threads=10 --max-time=300 threads run
ab
ab(apache bench)是一个常用的 HTTP 服务性能测试工具