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 | htop | top的增强版,以不同的颜色区分不同类型的进程,更加直观 | htop | atop | CPU、内存、磁盘和网络等各种资源的全面监控 | atop | vmstat | 包括系统范围的CPU平均负载,常用来分析CPU上下文切换和中断的次数,-t参数表示增加时间戳 | vmstat -a -t 1 | mpstat | 单个CPU统计信息,中断以及软中断数据,-P ALL表示监控所有CPU | mpstat -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 | perf | CPU性能计数器分析 | 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 中引入的全新平台级跟踪工具 | | AS | Android 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调度策略。
? ?
注意: 未进行性能分析前,一定不要提前性能优化; 提前性能优化是一个很操蛋的事情!!
|