必须了解的Linux性能基础知识( 二 )

  • I/O 等待 CPU 高,说明等待 I/O 的时间比较长,所以应该着重排查系统存储是不是出现了 I/O 问题 。
  • 软中断和硬中断高,说明软中断或硬中断的处理程序占用了较多的 CPU,所以应该着重排查内核中的中断服务程序 。
  • 平均负载第二能想到的就是平均负载 。很多人会认为,平均负载不就是单位时间内的 CPU使用率吗?其实并非如此 。下面我们来一起熟悉下什么是平均负载 。
    通俗地说,平均负载是指单位时间内系统处于可运行状态和不可中断状态的平均进程数,即平均活跃进程数 。从定义我们可以解读到其实跟 CPU使用率无直接关系 。
    linux 将进程的状态划分为以下几种:
    R 是 Running 的缩写,表示进程正在运行或者正在等待运行 。
    D 是 Disk Sleep 的缩写,为不可中断睡眠状态,进程正与硬件进行交互,交互过程不允许被其他进程打断,以防止数据丢失 。
    Z 是 Zombie 的缩写,表示僵尸进程,进程实际已经结束,但是父进程还没回收其资源,就会出现该状态 。
    S 是 Interruptible Sleep 的缩写,称为可中断睡眠状态,表示进程因等待某个事件而被系统挂起 。
    I 是 Idle 的缩写,为空闲状态,用于不可中断睡眠的内核线程上 。
    T 是 Traced 的缩写,表示进程处于暂停状态 。
    X 是 Dead 的缩写,表示进程已经消亡 。
    如何查看通常使用 uptime 或 top 命令查看 。例如,uptime 的输出格式为:
    $ uptime15:22:50 up 284 days,4:40,3 users,load average: 10.06, 12.15, 12.33输出分别表示为当前时间、系统运行时间、正在登录用户数以及过去 1 分钟,5 分钟,15 分钟的平均负载 。输出这三个时间的平均负载有什么含义呢?
    • 数值基本相同,说明系统负载趋于平稳 。
    • 数值从过去 15 分钟到过去 1 分钟逐渐升高,说明系统运行任务在增多,需要我们去观察和判断这种升高是否合理 。
    • 数值从过去 15 分钟到过去 1 分钟在逐渐降低,说明系统运行任务在减少 。
    基于此就可以粗略判断当前的系统负载情况 。上面的例子可以看到目前的系统负载下降的 。
    多少为合理平均负载这一数据没有针对 CPU 个数作归一化处理,因此最理想情况是平均负载等于 CPU 的个数 。在评判当前系统是否过载时,首先需要知道当前系统的 CPU 个数,可以通过 top 或者 lscpu 查看 。例如:
    $ lscpuArchitecture:x86_64CPU op-mode(s):32-bit, 64-bitByte Order:Little EndianCPU(s):24...当知道了 CPU 个数后,就可以结合平均负载来判断当前系统的运行情况了 。一旦负载过高,会导致进程响应变慢,影响服务的正常功能 。故当出现负载有明显升高趋势时,就需要我们去分析和调查了 。通常认为平均负载低于 CPU 数量 70% 时为合理状态,但不是绝对的,还需要参考负载的变化趋势来作判断 。
    CPU上下文切换前面描述了 linux 系统会在很短的时间内把 CPU 轮流分配给任务(进程),造成多个任务同时运行的错觉 。而这些任务都是从哪里加载以及开始运行的呢?这就引出了 CPU上下文 。CPU寄存器和程序计数器被叫做 CPU 的上下文,那么,CPU寄存器和程序计数器分别有什么作用呢?
    • CPU寄存器,存放数据的小型存储区域,用来暂时存放参与运算的数据和运算结果 。
    • 程序计数器,用来存储 CPU 下一条指令位置 。
    而 CPU上下文切换,就是把前一个任务的 CPU上下文保存起来,然后加载新任务的上下文到寄存器和程序计数器中,最后跳转到程序计数器所指位置,执行新任务 。根据任务的不同,可以分为三种切换场景:进程上下文切换、线程上下文切换以及中断上下文切换 。
    进程上下文切换提到进程上下文切换,就不得不提到系统调用 。linux 按照特权等级,把进程的运行空间划分为内核空间和用户空间 。
    • 内核空间,具有最高权限,可以访问所有资源 。
    • 用户空间,访问受限,不能直接访问内存等硬件设备,只能通过系统调用到内核中,由内核访问 。
    系统调用和普通函数调用非常相似,只不过,系统调用由操作系统核心提供,运行于内核态,而普通函数调用由函数库或用户提供,运行于用户态 。比如,某一进程需要查看文件内容时,就需要系统调用来完成:首先调用 open() 打开文件,通过 read() 读取文件内容,并通过 write() 写到到标准输出,最后通过 close() 关闭文件 。系统调用结束后,CPU寄存器恢复到原来保存的用户态,切换到用户空间,继续执行进程 。


    推荐阅读