[性能优化] - cpu调度原理

目录

 

[性能优化] - cpu调度原理

1 背景

2 基本概念

3 CPU调度程度

3.2 O(1)调度程序

3.3完全公平调度程序CFS

4 CPU与性能优化

5 总结


[性能优化] - cpu调度原理

second60 20180801

 

1 背景

linux系统是一个多任务实时操作系统。这里的多任务就CPU调度的任务。

在linux操作系统中,CPU是并不知道进程存在的,进程是以任务task_structure的形式让CPU分时间片一个一个去处理。

 

问题来了:CPU是怎么做到多任务的切换分时间片的呢?是的,答案就是CPU调度机制。在多任务处理机制下,多个程序共享CPU,它们在CPU上轮流运行。

2 基本概念

任务:CPU执行的一个时间片。内核中会对每个进程task_structure,优先级和阻塞率等,进   行分时间片。

调度机制:对任务进行切换调度的一种机制。

一个单独的CPU,同一时间只能对一个任务进行处理。

3 CPU调度程度

内核使用进程调度程序来确定哪个程序在哪个给定时间点运行。为了工作正常,进程调度程序必须合理调度不同资源。它必须很快确定接下来轮到哪个进程得到CPU。保证各进程得到的CPU时间是公平的,同时允许高优先级的进程得到更大的CPU时间,或抢占较低优先级的进程CPU时间。

三种调度程序

  1. O(n)调度程序
  2. O(1)调度程序
  3. CFS调度程序

 

3.1 O(n)调度程序

这是内核2.6以前的调度程序,原理是:它必须扫描整个进程列表,根据优先级等条件,以便找到下一个要运行的进程。采用的是轮询的方法。

 

O(n)调度程序的时间复杂度为O(n),如果进程越多,轮询时间越长,效率也越差。

3.2 O(1)调度程序

内核2.6中提出并使用,原理:为每个CPU使用2个队列,一个运行队列和一个进期队列。调度程序根据它们的优先级将它们放置在运行队列的进程列表中,需要调度时,取出运行队列中的最高优先级列表中的第一个进程,并运行它。

调度程序基于进程优先级和以前的阻塞率给进程分配一个时间片,当进程时间片用完后,调度程序将其移动到过期队列相应的优先级列表。然后它从运行列中取出下一个具有最高优先级的进程,重复以上过程。一旦运行队列中不再有进程等待,调度程序就将过期队列转变为新的运行队列,之前的运行队列成为新的过期队列,开始再次循环。

流程:

  1. 调度程序根据优先级将进程放置在运行队列
  2. 调度程序将从运行队列取出最高优先级的第一个进程运行
  3. 调度程序基于进程优先级和以前的阻塞率给进程分配一个时间片
  4. 调度程序将其移动到过期队列相应的优先级列表
  5. 从运行列中取出下一个具有最高优先级的进程,重复以上过程
  6. 当运行队列为空时,过期队列和运行队列变换,开次开始循环。

优点:

  1. 时间复杂度为O(1),效率好,每个进程都会执行,不会饿死低优先级进程。
  2. 支持非统一内存架构NUMA
  3. 支持对称多线程处理器SMP

缺点:交互式进程会得到较高的优先级,拥有较长的时间片。

问题:

  1. 多CPU时,怎么来负载均衡进程数量?(进程数平均)
  2. 怎么来保证每个CPU的能比较平均地运行?(时间平均)
  3. 会不会出现某个CPU运行效率很高,某个CPU运行效率很低?

 

3.3完全公平调度程序CFS

CFS(Completely Fair Scheduler) 完全公平调度程序,在内核 2.6.23中引入,因为不能解决上面的问题,所以用来取化O(1)。

 

CFS基于“虚拟时间”的红黑树。虚拟时间基于进程等待运行时间、竞争CPU进程数量及进程优先级来计算。

具有最多虚拟时间的进程(最长等待CPU时间)得到使用CPU的权限。随着它使用CPU时间的增加,它的虚拟时间在减少。一旦进程不再拥有最多的虚拟时间,它将被拥有最多虚拟时间的进程抢占。

流程:

  1. 调度程序根据进程等待运行时间、竞争CPU进程数量及进程优先级来计算进程虚拟时间
  2. 调度程序取出虚拟时间最多的进程并运行
  3. 虚拟时间随着使用时间而减少
  4. 进程不再拥有最多的虚拟时间,它将被拥有最多虚拟时间的进程抢占。

优点:

  1. 代码简单
  2. 性能比较好
  3. 多核中,每个进程也比较均衡地分到时间片

 

4 CPU与性能优化

CPU是性能优化,最直接的一方面。通过观察CPU使用情况,可以了解当前系统CPU的负载,进程的使用情况是否有异常等。

 

CPU衡量标准:

  1. CPU使用率:描述了每个处理器整体使用率。
    1. 如果在一段时间持续时间内CPU使用率超过80%,则要查看是什么原因导致CPU持续高:高峰期,代码逻辑问题,定时批量处理等
    2. 如果是正常逻辑,那么可能是处理器瓶劲,是否应考虑分布式处理,或换更好CPU的机器。
    3. CPU高,通常情况下是一件好事,说明CPU使用率高。如果持续高,那么也要考虑下高峰期高并发的临时方案,如启运个备用进程防止负载过高;拆分业务到不同进程里,分多台机器处理;给进程一个最大限制的处理业务量,当超过这个量就不再处理新业务或等待处理等。
  2. 用户进程消耗CPU的时间:描述了CPU花费在用户进程的百分比。
    1. 如果值比较高,说明进程处理利用率比较好。如果多核的值比较平均是更好了。
    2. 但一直过高,可以通过火陷图等工具,查看进程函数的调用是否正常,如果不正常那么可对代码进行优化,如算法的优化,循环的优化,调用次数的优化等。
  3. 内核操作消耗CPU时间:描述了CPU花费在内核操作的百分比,包括IRQ(中断请求)和softirq时间。
    1. 内核消耗的CPU,主要是在中断请求,网卡,驱动程序等。如果CPU越高,那么说明可能存在瓶颈,如网卡并发十万数据,sys非常高,说明sys大部份时间花在了网卡中断上。
    2. 正常情况下,内核操作上的时间尽可能少。
  4. 等待:CPU花费在等待上的时间总量。
    1. 如IO操作等待,阻塞
    2. 系统不应花太多时间在等待上
    3. 如果等待时间太长,应检查IO子系统性能,是否IO操作不过来,或磁盘损坏。
    4. 如果IO操作不过来,是否考虚缓存设计,或更新更快速度磁盘等
  5. CPU空闲时间:描述了系统空闲等待任务的CPU百分比。
    1. 为了最大效率的使用CPU,当然是CPU空闲时间越少越好
  6. nice消耗CPU时间:描述了CPU花费在re-nicing进程()更改进程执行顺序和优先级) 的时间百分比。
    1. 这个也不用说了,越小越好,小说明执行变更少。
  7. 平均负载:是1min,5min,15min, 队列中等待处理进程数+等待不可中断任务被完成的进程数之和。
    1. load average分1min, 5min, 15min。
    2. 队列中等待处理的进程数(TASK_RUNNING状态的进程)
    3. 等待不可中断任务被完成的进程数(TASK_UNINTERRUPTIBLE状态的进程)
    4. 如果进程请求CPU时间被阻塞,负载增加
    5. 如果每个进程得到直接访问CPU的时间,没有在CPU周期丢失,负载减小
    6. 很多文章说,负载的值为核数的两倍或三倍时,是比较优的。比如,四核,那么负载为8是比较优的,因为一个正在运行,一个正在等待运行。建议两倍。
  8. 可运行的进程:描述已经准备好执行的进程数。
    1. 在一段持续时间内,这个值不应该超过处理器数量的10倍。
    2. 超进10倍,可能是处理器瓶颈
  9. 阻塞的进程:不被执行的进程数。
    1. 因为进程要等待IO操作结整,所以阻塞
    2. 阻塞的进程数能反映出是否有IO瓶颈
  10. 上下文切换:系统发生线程之间切换的数量。
    1. 上下文切换越少越好,切换意味着CPU的无用消耗,导致CPU缓存刷新。
    2. 大量上下文切换如果与大量中断有关,可能是驱动程序或应用程出现问题。
  11. 中断:包括硬中断、软中断、CPU时钟中断等。
    1. 硬中断:硬件发出的消息导致中断,如键盘按键、鼠标点击、网卡网络数据到达等。
    2. 软中断:代码引发的中断,如除0操作、空指针操作等。
    3. 较高的中断值,可能是软件的瓶劲,也可能是驱动程序的瓶颈。

 

5 总结

本节讲解了CPU的调度原理,能让读者了解CPU是怎么样对任务(进程)进行调度的。同时结合实际,分享了CPU的实际中的性能分析。

 

猜你喜欢

转载自blog.csdn.net/second60/article/details/81335697