1. 概述:

CPU推动了所有软件的运行,因而通常是系统性能分析的首要目标;现代系统一般有多颗CPU,通过内核调度器共享给所有运行软件。当需求的CPU资源超过了系统力所能及的范围时,进程里的线程(或者任务)将会排队,等待轮候自己运行的机会。等待给应用程序的运行带来严重延时,使得性能下降。

我们可以通过仔细检查CPU的用量来寻找性能改进的空间,还可以去除以下不需要的负载。从上层来说,可以按照进程,线程或者任务来检查CPU的用量。从下层来看,可以剖析并研究应用程序和内核的代码路径。在底层,可以研究CPU指令的执行和周期行为。

此外,内核I/O对CPU性能有很大影响。

2. 性能指标

    2.1 CPU性能指标表格:

CPU性能指标CPU使用率用户CPU用户态CPU时间
系统CPU内核态CPU时间
iowait等待I/O的CPU时间
硬中断硬中断CPU时间
软中断软中断CPU时间
窃取CPU被其他虚拟机占用的CPU时间
客户CPU运行虚拟机的CPU时间
上下文切换自愿上下文切换自愿上下文切换,是指进程无法获取所需资源,导致上下文切换。比如I/O,内存等资源不足时就会发生资源上下文切换。
非自愿上下文切换非自愿上下文切换,是指进程由于时间片已到等原因,被系统强制调度,进而发生的上下文切换。比如
大量进程都在争抢CPU时,就容易发生非自愿上下文切换。
平均负载单位时间内,系统处于可运行状态和不可中断状态的平均进程数,也就是平均活跃进程数。
CPU缓存命中率如果 CPU 所要操作的数据在缓存中,则直接读取,这称为缓存命中。命中缓存会带来很大的性能提升,因此,我们的代码优化目标是提升 CPU
缓存的命中率。
     2.2 CPU缓存命中率 

       
由于CPU发展的速度远快于内存的发展,CPU的处理速度就比内存的访问速度快得多;这样CPU在访问内存的时候,免不了要等待内存的响应。为了协调这两者的巨大性能差距,CPU缓存就出现了。

       

L1缓分成两种,一种是指令缓存,一种是数据缓存。L2缓存和L3缓存不分指令和数据。L1和L2缓存在第一个CPU核中,L3则是所有CPU核心共享的内存。L1、L2、L3的越离CPU近就越小,速度也越快,越离CPU远,速度也越慢。再往后面就是内存,内存的后面就是硬盘。我们来看一些他们的速度:

*
L1 的存取速度:4 个CPU时钟周期

*
L2 的存取速度:11 个CPU时钟周期

*
L3 的存取速度:39 个CPU时钟周期

*
RAM内存的存取速度 :107 个CPU时钟周期

如果 CPU 所要操作的数据在缓存中,则直接读取,这称为缓存命中。命中缓存会带来很大的性能提升,因此,我们的代码优化目标是提升 CPU 缓存的命中率。 

3. 分析工具:

3.1 工具汇总:

CPU分析工具
工具描述常用用法
uptime平均负载,-d参数表示高亮显示变化的区域watch -d uptime
top平均负载,运行队列,整体的CPU使用率以及每个进程的状态、优先级和CPU使用率top
htoptop的增强版,以不同的颜色区分不同类型的进程,更加直观htop
atopCPU、内存、磁盘和网络等各种资源的全面监控atop
vmstat包括系统范围的CPU平均负载,常用来分析CPU上下文切换和中断的次数,-t参数表示增加时间戳vmstat -a -t 1
mpstat单个CPU统计信息,中断以及软中断数据,-P ALL表示监控所有CPUmpstat -P ALL 1
ps进程状态ps aux
sar系统整体的CPU使用率,包括可配置的历史数据
sar -o 日期

如,当天为某月24日

sar -o 24

2. 查看: sar

pidstat
每个进程/线程CPU用量分解,加上-w选项就可以查看每个进程上下文切换的情况了,加上-t选项就可以查看进程下的线程情况了,-u参数表示输出CPU使用指标
pidstat -w -u  1
pidstat -wt -u 1
perfCPU性能计数器分析
1. perf record -g

2. perf report

/proc/interrupts

系统中断数据,watch -d参数表示高亮显示变化的区域(监控)

1. cat /proc/interrupts

2. watch -d /proc/interrupts

systrace可记录短时间内的设备活动,并保存在压缩的文本文件中。该工具会生成一份报告,其中汇总了 Android 内核中的数据,例如 CPU
调度程序、磁盘活动和应用线程
perfetto是 Android 10 中引入的全新平台级跟踪工具
ASAndroid Studio 中分析应用的 CPU 使用率和线程活动
3.2 常用工具

*         top
*         mpstat
*         vmstat
*         pidstat

 

  

4. 优化方案

 4.1 应用程序优化

  从应用程序角度来说,减低CPU使用率最好的方法当然是,排除所有不必要的工作。

  优化方法有: 

*   编译器优化:
编译器及其提供的代码选项,对CPU性能有很大影响。一般的选项包括了编译为64位而非32位程序,以及优化级别。编译优化能对CPU指令的选择和部署做优化。gcc编译器的优化区间是0~3,3是最大数目的优化;比如-O2,开启后自动对应用程序的代码进行优化。
*   异步处理:
使用异步处理,可以避免程序因为等待某个资源而一直阻塞,从而提升程序的并发处理能力,比如,把轮询替换为事件通知,就可以避免轮询耗费的CPU问题。
*   多线程代替多进程:相对于进程的上下文切换,线程的上下文切换并不切换进程地址空间,因此可以降低上下文切换的成本。
*   合理利用缓存:优化代码,善用缓存,经常访问数据或者计算过程中的步骤,已提升CPU缓存命中率为目标优化Code。
*    I/O以及内存优化: // I/O优化章节会重点涉及
   4.2 系统优化:

*     进程绑定:一个进程可以绑定在一个或者多个CPU上,这样可以通过提高缓存温度和内存本地性来提高性能。//如 cpuset
*     独占CPU组:
Linux提供了CPU组,允许编组CPU并为其分配进程。这和进程绑定类似,可以提高性能,但还可以通过使得CPU组独占----不允许其他进程使用,进一步提高性能。这种权衡另 一方面减少了系统其他部分的可用CPU数量。
*     资源控制:除了把进程和整个CPU关联以外,现代操作系统还对CPU用量分配提供了细粒度资源控制。//如 cgroups
*     优先级调整:
使用nice调整进程优先级,正值调低优先级,负值调高优先级。适当降低非核心应有的优先级,增高核心应用的优先级,可以确保核心应用得到优先处理。
*     中断负载均衡
:无论是软中断还是硬中断,他们的中断处理程序都可能会耗费大量CPU。开启irqbalance服务或者配置smp_affinity,就可以把中断处理过程自动负载均衡到多个CPU上。
*    CPU调度优化:采用特定的CPU调度策略,比如EAS调度策略。
   

注意: 未进行性能分析前,一定不要提前性能优化; 提前性能优化是一个很操蛋的事情!!

技术
下载桌面版
GitHub
Gitee
SourceForge
百度网盘(提取码:draw)
云服务器优惠
华为云优惠券
腾讯云优惠券
阿里云优惠券
Vultr优惠券
站点信息
问题反馈
邮箱:[email protected]
吐槽一下
QQ群:766591547
关注微信