6.1 术语
1.处理器:插到系统插槽或者处理器板上的物理芯片,以核或者硬件线程的方式包含了一块或者多块cpu
2.核:一颗多核处理器上的一个独立cpu实例。核的使用是处理器扩展的一种方式,又称为芯片级多处理(CMP).
3.硬件线程:一种支持在一个核上同时执行多个线程的cpu架构,每个线程是一个独立的cpu实例。这种扩展方法又称为多线程。
4.cpu指令:单个cpu操作,来源于它的指令集。指令用于算术操作,内存IO,以及逻辑控制。
5.逻辑cpu:又称为虚拟处理器,一个操作系统cpu的实例。处理器可以通过硬件线程,一个核,或者一个单核的处理器实现。
6.调度器:把cpu分配给线程运行的内核子系统。
7.运行队列:一个等待cpu服务的可运行线程队列。
6.2 模型
6.2.1 CPU 架构
每个硬件线程都可以按照逻辑cpu寻址。
6.2.2 CPU 内存缓存
cpu 寄存器,一级缓存,二级缓存,三级缓存,主存,存储设备
6.2.3 CPU 运行队列
正在排队和就绪运行的软件线程数量是一个很重要的性能指标,表示了cpu的饱和度。花在等待cpu运行上的时间又被称为运行队列延时或者分发器队列延时。
对于多处理器系统,内核通常为每个cpu提供了一个运行队列,并尽量使得现场每次都被放到同一个队列中。这意味着线程更有可能在同一个cpu上运行,因为cpu缓存里保存了
它的数据。在NUMA系统中,这会提高内存本地性,从而提高系统性能。这同样避免了队列操作的线程同步开销(mutex锁)。
6.3 概念
6.3.1 时钟频率
时钟是一个驱动所有处理器逻辑的数字信号。每个cpu指令都可能会花费一个或者多个时钟周期(称为cpu周期)来执行。cpu以一个特定的时钟频率执行。
有些处理器可以改变时钟频率,升频改进性能或者降频减少能耗。
6.3.2 指令
一个指令包含以下步骤,每个都由cpu的一个叫做功能单元的组件处理:
1.指令预取
2.指令解码
3.执行
4.内存访问
5.寄存器写回
最后两步是可选的,取决于指令本身。许多指令仅仅操作寄存器,并不需要访问内存。这里的每一步都至少需要一个时钟周期来执行。内存访问经常是最慢的,因为它需要
几十个时钟周期读或写主存,在此期间指令执行陷入停滞。这就是cpu缓存如此重要的原因:它可以极大的降低内存需要访问的周期数。
6.3.3 指令流水线
指令流水线是一种cpu架构,通过同时执行不同指令的不同部分,来达到同时执行多个指令的结果。
6.3.4 指令宽度
同一种类型的功能单元可以有好几个,这样每个时钟周期里就可以处理更多的指令。这种cpu架构被称为超标量,通常和流水线一起使用达到高指令吞吐。指令宽度描述了同时
处理的目标指令数量。现代处理器一般为宽度3或者4,意味着它们可以在每个周期里最多完成3~4个指令。
6.3.5 CPI,IPC
每指令周期数(CPI)是一个很重要的高级指标,用来描述cpu如何使用它的时钟周期,同时也可以用来理解cpu使用率的本质。这个指标也可以被表示为每周期指令数,即CPI的
倒数。
CPI 较高代表cpu经常陷入停滞,通常都是在访问主存。而较低的CPI则代表cpu基本没有停滞,指令吞吐量较高。这些指标表明了性能调优的主要方向。
6.3.6 使用率
cpu使用率通过测量一段时间内cpu实例忙于执行工作的时间比例获得,以百分比表示。高cpu使用率并不一定代表着问题,仅仅表示系统正在工作。
cpu使用率通常被分为内核时间和用户时间两个指标。
6.3.7 用户时间/内核时间
cpu花在执行用户态应用程序代码的时间成为用户时间,而执行内核态代码的时间被称为内核时间。内核时间包括系统调用,内核线程和中断的时间。
计算密集的应用程序几乎会把大量的时间用在用户态代码上。IO密集型的应用程序的系统调用频率比较高,通过执行内核代码进行IO操作。
6.3.8 饱和度
一个100%使用率的cpu被称为是饱和的,线程在这种情况下会碰到调度延时,因为它们需要等待才能在cpu上运行,降低了总体性能。这个延时是线程花在等待cpu运行队列或
其他管理线程的数据结构上的时间。
6.3.9 抢占
允许更高优先级的线程抢占当前正在运行的线程。
6.3.10 优先级反转
优先级反转指的是一个低优先级线程拥有了一项资源,从而阻塞了高优先级线程运行的情况。这降低了高优先级工作的性能,因为它被迫阻塞等待。
6.3.11 多进程,多线程
应用程序在多cpu上扩展的技术分为多进程和多线程。
6.3.12 字长
处理器是围绕最大字长设计的---32位或者64位。这是整数大小和寄存器宽度。字长也普遍使用,表示地址空间大小和数据通路宽度。更宽的字长意味着更好的性能,虽然它并没有听上去那么简单,
更宽的字长可能会在某些数据类型下因未使用的位而导致额外的内存开销。数据的大小也会以为指针大小的增加而增加,导致需要更多的内存IO。
6.3.13 编译器优化
应用程序在cpu上的运行时间可以通过编译器选项来大幅改进。编译器也频繁的更新以利用最新的cpu指令集以及其他优化。
6.4 架构
6.4.1 硬件
cpu硬件包括了处理器和它的子系统,以及更多处理器之间的cpu互连。
处理器:
控制器,cpu的心脏,运行指令预取,解码,管理执行以及存储结果。
寄存器
算术逻辑单元
浮点单元
MMU
TLB
一级指令缓存
一级数据缓存
二级指令缓存
三级缓存
总线接口
其他性能组件可能还包括以下内容:
1.P-cache : 预取缓存(每cpu一个)
2.W-cache : 写缓存(每cpu一个)
3.时钟:cpu时钟信号生成器
4.时间戳计数器:为了高精度时间,由时钟递增。
5.微代码ROM:快速把指令转换成电路信号
6.温度传感器:温度监控
7.网络接口:如果集成在芯片里(提高性能)
cpu缓存:
1.一级指令缓存(I$)
2.一级数据缓存(D$)
3.转移后备缓冲器(TLB)
4.二级缓存(E$)
5.三级缓存(可选)
延时:
多级缓存是用来取得大小和延时平衡的最佳配置。
相连性:
相连性是定位缓存新条目范围的一种缓存特性。类型如下:
1.全关联
2.直接映射
3.组关联
缓存行:
cpu 缓存的另外一个特质是缓存行大小。
缓存一致性:
内存可能会同时被缓存在不同处理器的多个cpu里。当一个cpu修改了内存,所有的缓存都需要知道它们的缓存拷贝已经失效了,应该被丢弃。这样过程叫缓存一致性。
MMU:
MMU 负责虚拟地址到物理地址的转换。这个MMU通过一个芯片上的TLB缓存地址转换。主存(DRAM)里的转换表,又叫页表,处理缓存未命中的情况。页表由MMU(硬件)直接读取。
互联:
对于多处理器,处理器通过共享系统总线后者专用互连连接起来。这与系统的内存架构有关,统一访问内存(UMA)或者NUMA。
CPU 性能计数器:
cpu性能计数器(CPC)有许多别名,包括性能测量点计数器(PIC),性能监控单元(PMU),硬件事件和性能监控事件。它们是可以计数低级cpu活动的处理器寄存器。
6.4.2 软件
调度器:
内核cpu调度器的主要功能:
1.分时,可运行线程之间的多任务,优先执行最高的任务
2.抢占,一旦有高优先级线程变为可运行状态,调度器能够抢占当前运行的线程,这样较高优先级的线程可以马上开始运行。
3.负载均衡,把可运行的线程移到空闲或者较不繁忙的cpu队列中。
调度类:
调度类管理了可运行线程的行为,特别是它们的优先级,还有cpu时间是否分片,以及这些时间片的长度。
用户线程的优先级受一个用户定义的nice值影响。
6.5 方法
6.5.1 工具法
把可用的工具全部用一遍,检查它们提供的关键项指标。
6.5.2 USE 方法
对于每个cpu,检查以下内容:
1.使用率,cpu繁忙的时间
2.饱和度,可运行线程排队等待cpu的程度
3.错误,cpu错误
6.5.3 负载特征归纳
cpu 负载特征规范的基本属性有:
1.平均负载(使用率+饱和度)
2.用户时间与系统时间之比
3.系统调用频率
4.自愿上下文切换频率
5.中断频率
高级负载特征归纳/检查清单:
1.整个系统范围内的cpu使用率是多少?每个cpu呢?
2.cpu负载的并发程度如何?是单线程吗?有多少线程?
3.哪个应用程序或者用户在使用cpu?用了多少?
4.哪个内核线程在使用cpu?用了多少?
5.中断的cpu用量是多少
6.cpu互连的使用率是多少
7.为什么cpu被使用(用户和内核级别调用路径)?
8.遇到了什么类型的停滞周期?
6.5.4 剖析
6.5.5 周期分析
通过使用cpu性能计数器(cpc),我们能够以周期级别理解cpu使用率。
6.5.6 性能监控
性能监控可以发现一段时间内活跃的问题和行为模式。关键的cpu指标如下:
1.使用率
2.饱和度
6.5.7 静态性能调优
通过设置nice值以调整进程优先级。
6.5.8 优先级调优
6.5.9 资源控制
6.5.10 CPU 绑定
把进程和线程绑定在单个cpu或者一组cpu上。这可以增加进程的cpu缓存温度,提高它的内存IO性能。对NUMA系统这可以提高内存本地性,同样也能提高性能。
这个方法有以下两个实现方式:
1.进程绑定:配置一个进程只跑在单个cpu上,或者预定义cpu组中的一个。
2.独占cpu组:分出一组cpu,让这些cpu只能运行指定的进程。这可以大大提升cpu缓存效率,因为当进程空闲时,其他进程不能使用cpu,保证了缓存的温度。
在linux上可以通过 cpuset 实现。
6.5.11 微型基准测试
6.5.12 扩展
6.6 分析
6.6.1 uptime
6.6.2 vmstat
6.6.3 mpstat
6.6.4 sar
6.6.5 p
6.6.6 top
6.6.7 prstat
6.6.8 pidstat
6.6.9 time 和ptime
6.6.10 DTrace
6.5.11 SystemTap
6.6.12 perf
perf 子命令:
1.annotate,读取perf.data并显示注释过的代码
2.diff,读取2个perf.data文件并显示两份剖析信息之间的差异
3.evlist,列出一个 perf.data 文件里的事件名称
4.inject,过滤以加强事件流,在其中加入额外的信息
5.kmem,跟踪/测量内核(slab)属性的工具
6.kvm,跟踪/测量kvm客户机操作系统的工具
7.list,列出所有的符号事件类型
8.lock,分析锁事件
9.probe,定义新的动态跟踪点
10.record,运行一个命令,并把剖析信息记录在perf.data中
11.report,读取perf.data并显示剖析信息
12.sched,跟踪/测量调度器属性的工具
13.script,读取perf.data并显示跟踪输出
14.stat,运行一个命令并收集性能计数器统计信息
15.timechart,可视化某一个负载期间系统总体性能工具
16.top,系统剖析工具
//-a 所有cpu,-F 997 997Hz的频率,-g 对调用栈,取样 10s(sleep 10)
perf record -a -g -F 997 sleep 10
//下面的命令执行了 command 并创建文件perf.data
perf record -g command
//sched命令记录并报告调度器统计信息
perf sched record sleep 10
//stat 命令基于cpu为cpu周期行为提供了一个概要总结。
perf stat gzip file1
//列出了其他可以检查的计数器
perf list
perf stat -e 事件
//可以与各种软件性能测量点配合,用来跟踪内核调度器的活动
perf record -e
6.6.13 cpustat
6.6.14 其他工具
6.6.15 可视化
1.cpu使用率热图
2.cpu亚秒偏移量热图
3.火焰图
特征:
1.每个框代表栈里的一个函数(一个栈帧)
2.Y轴表示栈深浅(栈上的帧数)。顶部的框表示在cpu上执行的函数。下面的都是它的祖先调用者。函数下面的函数即使其父函数。
3.X轴横跨整个取样数据。它并不像大多数图那样,从左到右表示时间的流逝,其左右顺序没有任何含义(按字母排序)
4.框的宽度表示函数在cpu上运行,或者是它的上级函数在cpu上运行的时间(基于取样计数)。更宽的函数可能比更窄函数慢,也可能是因为只是很频繁的被调用。
调用计数不显示。
5.如果是多线程运行,而且抽样是并发的情况,抽样计数可能会超过总时间。
6.7 实验
6.7.1 Ad Hoc
6.7.2 SysBench
6.8 调优
6.8.1 编译器选项
6.8.2 调度优先级和调度类
nice.
6.8.3 调度器选项
6.8.4 进程绑定
taskset.
6.8.5 独占CPU 组
6.8.6 资源控制
cgroups.
6.8.7 处理器选项(BIOS)