CPU基础及调优

阅读(1,534)

一:CPU基础: 

CPU拖动了所有软件的运行,因此通常是性能分析的首要目标,目前的服务器支持多颗CPU,通过系统内核调度器共享给所有软件运行,当需求的CPU资源超过了系统能力所负责的范围时,进程里的线程或者任务就会进行排队等待,等候自己的运行机会,如果等待的时间较长就会给应用程序的运行带来严重的延时导致性能下降。

1.1:CPU术语:

1.1.1:处理器:插到主板上的物理芯片。
1.1.2:核:一个物理CPU的多个独立CPU实例,核的使用是CPU扩展的一种方式,又称为芯片级多处理(chip-level multiprocessing,简称CMP)。
1.1.3:硬件线程:一种支持在一个核上同时执行多个线程的CPU架构,每个线程都是一个独立的CPU实例,这种扩展的方法又称之为多线程。
1.1.4:CPU指令:单个CPU操作,来源于他的指令集,指令用于算数操作、内存I/O、预计逻辑控制等。
1.1.5:逻辑CPU:又称为虚拟机处理器,目前大多数指的是虚拟化技术虚拟的CPU实例。
1.1.6:调度器:把CPU分配给线性运行的内核子系统。
1.1.7:运行队列:一个等待CPU服务的可运行线程队列。

1.2:CPU基础:

1.2.1:CPU组成部分:

一个四核心八线程的CPU,在系统看来就等于有了8个CPU,其每个硬件线程都可以按逻辑CPU寻址,但是系统可能会有一些其他的信息,比如那些CPU在同一个核上,这样可以提高调度的质量。

1.2.2:CPU缓存:

为了提高I/O的性能,CPU提供了多种硬件缓存,如下:

CPU–>-一级缓存–>二级缓存–>三级缓存–>内存–>磁盘

1.2.3:CPU运行队列:

运行队列:指的是在线程运行之前等到CPU的排队等待时间

运行时间:该线程在CPU上的执行时间

I/O返回队列:线程执行完成后等待数据返回的队列时间

#下图中A线程是运行队列,B线程是运行时间,C线程是I/O等待时间

1.2.4:CPU时钟频率:

时钟是一个驱动所有处理逻辑的数字信号,每个CPU指令都可能会花费一个或多个时钟周期或称为CPU周期来执行完成,CPU以一个特定的时钟频率执行,例如一个1GHz的CPU每秒运行10亿个时钟周期,有些CPU可以改变时钟频率来提升性能或降低频率来减少功耗,频率可以根据操作系统变化,或者处理器自己进行动态调整,时钟频率经常被当做性能的主要指标,但并不是完全正确的,还要取决于CPU周期里执行的具体任务内容,如果大部分时间是停滞等待内存访问,那更快的执行实际上并不能提高CPU指令的执行效能或者负载吞吐量,另外还要看CPU物理核心数量等。

1.2.5:CPU指令:

使用# cat /proc/cpuinfo 查看CPU支持的指令:

是包含在CPU预设好的指令集的某个指令,一个指令包含以下步骤,每个指令都有CPU的一个叫做功能单元的组件处理:

指令预取—指令解码—执行—内存访问—寄存器返回

其中内存访问和寄存器不是每个指令都经过的,因为许多指令是仅仅操作寄存器,而不需要访问内存,这里每一个步骤都至少需要一个时钟周期来执行,内存和磁盘访问经常是最慢的,因为它通常需要几十个或更多的时钟周期读或写内存或磁盘设备,再次期间指令集陷入停滞(停滞期间的这些周期称为停滞周期),这就是CPU缓存为什么重要的原因,更大的CPU缓存可以极大的降低CPU访问内存的周期数。

1.2.6:指令流水线:

指令流水线是一种CPU结构,通过同时执行不能指令的不同部分来达到同时执行多个指令的结果,这类似于工厂的组装线,其生产的每个步骤都可以同时进行,提高吞吐量,上个步骤的一个指令要花费四五个时钟周期才能完成一个指令的执行,在执行指令的每一个步骤里,只有一个功能单元在运转而其他三四个是空闲的,而通过使用流水线,能同时在一个指令流水线运行与其一致的CPU指令,就像有5个流水线,可以并发处理5个指令,其在上一个步骤的每个过程分别在5个流水线同时执行,从而提高了处理效率,不必像上个步骤串行处理指令了。

1.2.7:指令宽度:

即同一种指令类型的功能单元可以有好几个,这样每个时钟周期里就可以处理更多的指令,这种CPU架构被称为超标量,通常和流水线一起使用以达到提高指令吞吐量,指令宽度描述了同时处理的目标指令数量,现代处理器一般为宽度3或宽度4,意味着它们可以在每个时钟周期里最多完成3-4个指令,具体结果取决于处理器本身,每个环节都有不同数量的功能单元处理指令,类似于,诶个流水线可以同时处理3-4个任务,将效率又提高3到4倍。

1.2.8:CPI和IPC:

每指令周期数CPI是一个很重要的高级指标,用来描述CPU如何使用它的时钟周期,同时也可以用来理解CPU效率的本质,这个指标也可以被表示为每周期指令数instructions per cycle(IPC),即CPI的倒数

1.2.9:使用率:

CPU使用率是通过测量一段时间内CPU实例忙于执行工作的时间比例获得到的值,用百分比表示,也可以通过测量CPU未运行内核空闲线程的时间得出,高CPU使用率并不一定代表着问题,仅仅表示系统在工作,在高使用率的情况下,性能并不会出现显著下降,因为内核支持了优先级、抢占和分时共享,这些概念加起来让内核决定了什么线程的优先级更高,并保证它优先运行,CPU使用率的测量包括了所有符合条件活动的时钟周期,包括内存停滞周期,因为CPU会经常因为停滞等待I/O而导致高使用率,而不仅仅是在执行指令,CPU使用率通常被分为内核时间和用户时间两个指标。
1.2.10:用户时间和内核时间:

CPU花在运行用户态应用应用程序代码的时间成为用户时间,而执行内核态代码的时间称为内核时间,内核态时间包括系统调用、内核线程和中断的时间,当在整个系统范围内进行测量的时候,用户时间和内核时间之比揭示了运行的负载类型,计算密集型的应用程序几乎会把大量的时间用在用户态代码上,比如图形处理、基因组学和数学分析,I/O密集型的的应用程序系统调用率比较高,通过执行内核代码进行I/O操作,I/O密集型的有数据库、视频网站等

1.2.11:饱和度:

100%使用率的CPU被称为是饱和的,线程在这种情况下会遇到调度器延时,因为它们需要等待才能在CPU上运行,这就降低了总体的性能,这个延时是花在等待CPU运行队列或者其他管理线程的数据结构上的时间,另一个CPU饱和与CPU资源控制有关,这个控制会在云计算情况下发生,尽管CPU并没有100%的被使用但是已经达到了控制的上限,因此可运行的线程就必须等待到它们的机会,饱和运行的CPU不像其他类型资源那样问题重重,因为更高优先级的线程可以抢占当前线程在CPU的运行位置。

1.2.12:抢占:

即运行更高优先级的线程抢占当前正在运行的线程并开始执行自己,这样就节省了更高优先级的线程的运行队列延时时间。

1.2.13:多进程和多线程:
目前处理器都可以实现逻辑上的多个CPU,对于应用程序来说,要想使用多CPU久需要开启不同的执行线程来并发运行,对于nginx来说,如果运行在16个CPU上就表示最快可以16倍以往的速度处理请求,但也要看I/0能不能跟得上等连贯问题,应用程序根据CPU数量进行扩展运行的能力又称为可扩展性,在多CPU上扩展的技术分为多进程和多线程,在linux上可以使用多进程和多线程,这两种技术是有任务实现的,多线程一般被认为优于多进程,但是其开发难于多进程,多进程和多线程关系如下:

1.2.14:进程优先级:

nice值:是使用nice或renice设置的优先级,范围是-19到20,值越小优先级别就越高,这个值不容易发生变化所以叫做静态优先级,linux一共有从0-139共计140个优先级,nice的值是从-20到19,映射到实际的优先级范围是100-139,新产生进程的默认优先级实际上就是对应nice值的0,正常情况下任何一个进程的优先级都是这个值,即使我们通过nice和renice命令调整了进程的优先级,那它的取值范围也不会超出100-139的范围,除非这个进程是一个实时进程,那么它的优先级才会变成0-99这个范围中的一个,这里也说明一点就是当前的Linux系统是一种支持实时进程的操作系统。

实时进程(RT)和非实时进程(CFS/O(1)):

实时进程就是要即刻进行处理的进程0-99,,是在指定的是时间内要要得到处理,其优先级更高,并且能够抢占其他非实时进程100-139

所有优先级是0-99的都是实时进程,而100-139的都是非实时进程,在系统中可以使用chrt命令来查看、设置一个进程的实时优先级状态:

1.2.15:进程调度器类型: 

RT:为实时类负载提供固定的高优先级,内核支持用户和内核级别的抢占,允许RT任务以短延时分发,优先级范围为0-99 

O(1):在Linux 2.6作为默认用户进程分时调度器引入,名字来源于算法复杂度O(1),先前的调度器包含了一个遍历所有任务的函数,算法复杂度为O(n),这样扩展性就成了问题,相当于与CPU消耗线程,O(1)调度器动态的提高了I/O消耗线程的优先级,以降低交互和I/O负载的延时。

CFS:Linux 2.6.23引入了完全公平的调度作为默认分时调度器,这个调度器使用红黑树取代了传统运行队列来管理任务,以任务的CPU时间作为键值,这样使得CPU的少量消费者相对于CPU消耗型负载更容易被找到,提高了交互和I/O消耗型负载的性能。

RT类支持SCHED_RR和SCHED_FIFO策略,而CFS类支持SCHED_NORMAL和SCHED_BATCH。

调度器策略如下:

RR:SCHED_RR是轮训调度,一旦一个线程用完了它的时间片,它就被挪到优先级运行队列的尾部,这样同等优先级的其他线程就可以得到运行。

FIFO:SCHED_FIFO:是一种先进先出的调度,一直运行队列头的线程直到它自愿退出,或者一个更高优先级的线程抵达,否则线程会一直运行,即便在运行队列当中存在相同优先级的其他线程。

NORMAIL:SCHED_NORMAIL之前称为SCHED_OTHER,是一种分时调度,是用用户进程的默认策略,调度器根据调度类动态调整优先级,对于O(1),时间片长度根据静态优先级设置,即更高优先级的工作分配到更长的时间,对于CFS,时间片是动态的。

BATCH:SCHED_BATCH和SCHED_NORMAIL类似,但期望 线程是CPU消耗的,这样就不会打断其他I/O消耗型交互工作。

当没有闲线程可以运行时,一个特殊的空闲任务又称为空闲线程作为替代运行在CPU,空闲线程的优先级会尽可能的降低,直达有其他线程可以运行,空闲线程通常被设计为通知CPU执行停止指令或减速以节省资源,CPU会在下一次硬件中断中醒来。

二:CPU监控方法

2.1:工具:

使用响应的工具检查其提供的关键指标,此方法比较简单,但是在某些情况下提供的帮助有限,并且会忽略一些问题,另外也比较耗时,常用的工具如下:

2.1.1:uptime:检查负载平均数以确认CPU是随时间上升还是下降,负载平均数超过了CPU数量通常代表CPU饱和。

2.1.2:vmstate:每秒运行vmstate,然后检查空闲列,查看还有多少余量,少于10%可能会存在问题。


Warning: count(): Parameter must be an array or an object that implements Countable in /home/nginx/wordpress/wp-includes/class-wp-comment-query.php on line 405

发表评论

邮箱地址不会被公开。 必填项已用*标注