• 浅谈cpu.idle和cpu.load


    1.概述

    大家经常对一个系统的容量进行评估时,会参考cpu.idle和cpu.load指标,但是这两个指标到底在什么区间,表示系统是正常或者异常呢,业内有不同的说法。因此本文搜集一些资料,并对一个系统进行压测,最终来获得一个比较客观的观点,如有不对,可以在评论区进行交流。

    在开始之前,我们必须对系统运转有一个整体的认识。在Linux内核中,每个进程都会被分配一个固定的时间片,默认为10ms,在这10ms中,该进程享有cpu的所有权。10ms看上去很短,但以2.6GHz的Intel处理器为例,10ms能够处理5000w条指令,对于绝大多数的应用这已经足够长了。如果该进程用完了10ms,或者有其他优先级高的进程发出请求,系统会触发一个中断,内核重新接管cpu,内核分配cpu给其他进程。10ms的分片让用户,也就是我们觉得我们的系统运转非常流畅,尽管我们可能同时开了很多的应用。

    2.cpu.idle

    CPU利用率主要分为用户态,系统态和空闲态,分别表示CPU处于用户态执行的时间,系统内核执行的时间,和空闲系统进程执行的时间,三者之和就是CPU的总时间,当没有用户进程、系统进程等需要执行的时候,CPU就执行系统缺省的空闲进程。CPU的利用率就是指非空闲进程占用时间的比例,即CPU执行非空闲进程的时间 / CPU总的执行时间。

    /proc文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间。它以文件系统的方式为内核与进程提供通信的接口。用户和应用程序可以通过/proc得到系统的信息,并可以改变内核的某些参数。由于系统的信息,如进程,是动态改变的,所以用户或应用程序读取/proc目录中的文件时,proc文件系统是动态从系统内核读出所需信息并提交的。

    cpu.idle是基于/proc/stat计算出来的,首先了解一下/proc/stat的各项指标的意义。

    代码块
    Shell
     
     
     
     
     
    [xietao02@gh-trip-open-opengateway-staging01 ~]$ cat /proc/stat
    cpu  30512019 2905 18888929 5215060855 449961 258 322293 482253 0
    cpu0 12054132 723 5666598 1297356736 439476 258 173174 175261 0
    cpu1 6256562 718 4332274 1305529992 4073 0 50163 105721 0
    cpu2 6252205 723 4470475 1305772598 3466 0 49552 102278 0
    cpu3 5949118 739 4419581 1306401527 2944 0 49403 98992 0
    intr 10488180092 119 7 0 0 0 0 0 0 1 0 0 33 104 0 0 68 0 0 0 0 0 0 0 0 0 10319942 0 336 0 18155452 0 14 0 265289852 3907 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    ctxt 18254375560
    btime 1516246663
    processes 13216259
    procs_running 1
    procs_blocked 0
    softirq 3948723530 0 1488253637 8488 455883603 17 0 179 392363322 13619548 1598594736
     

    第一行的数值表示的是CPU总的使用情况,cpu0、cpu1、cpu2、cpu3分别指每个cpu核心的cpu使用情况,下表解析第一行各数值的含义(单位:jiffies):

    user (30512019)

    从系统启动开始累计到当前时刻,用户态的CPU时间,不包含nice值为负进程。

    nice (2905)

    从系统启动开始累计到当前时刻,nice值为负的进程所占用的CPU时间

    system (18888929)

    从系统启动开始累计当前时刻,核心时间

    idle (5215060855)

    从系统启动开始累计到当前时刻,除IO等待时间以外其它等待时间

    iowait (449961)

    从系统启动开始累计到当前时刻,IO等待时间 2.5.41版本新增字段

    irq (258)

    从系统启动开始累计到当前时刻,硬中断时间 2.6.0版本新增字段

    softirq (322293)

    从系统启动开始累计到当前时刻,软中断时间 2.6.0版本新增字段

    stealstolen(482253)

    当一台物理机有多个虚拟机时,该cpu在其他虚拟机运行的时间

    which is the time spent in other operating systems when running in a virtualized environment 2.6.11

    guest(0)

    在cpu内核控制下,提供给在上面运行虚拟机占用的cpu时间

    which is the time spent running a virtual  CPU  for  guest operating systems under the control of the Linux kernel 2.6.24

    因为/proc/stat中的数值都是从系统启动开始累计到当前时刻的积累值,所以需要在不同时间点t1和t2取值进行比较运算,当两个时间点的间隔较短时,就可以把这个计算结果看作是CPU的即时利用率。

    其他参数的含义

    ctxt

    上下文切换次数

    btime

    系统启动到当前的时间

    sec

    process

    自启动以来,创建任务个数

    procs_running

    当前运行任务个数

    procs_blocked

    阻塞的任务个数

    2.1 CPU的即时利用率的计算公式(top falcon命令显示的):

    CPU在t1到t2时间段总的使用时间 = ( user2+ nice2+ system2+ idle2+ iowait2+ irq2+ softirq2+stealstolen2+guest2) - ( user1+ nice1+ system1+ idle1+ iowait1+ irq1+ softirq1+stealstolen1+guest1)

    CPU在t1到t2时间段空闲使用时间 = (idle2 - idle1)

    CPU在t1到t2时间段即时利用率 =  1 - CPU空闲使用时间 / CPU总的使用时间

    从top命令中看到的idle和falcon看到的cpu.idle都是以上的计算结果。

    从falcon上看到的cpu.busy=1-cpu.idle。

    2.2 CPU的平均利用率的计算公式(sar -u和ps aux命令显示的)

    1-(当前时间对应的cpu.idle值 )/ (当前时间对应的cpu.total值),cpu.total就是cpu那一行所有项的加和。

    2.3 进程和线程的cpu使用率

    /proc目录中有一些以数字命名的目录,它们是进程目录。系统中当前运行的每一个进程在/proc下都对应一个以进程号为目录名的目录/proc/pid,它们是读取进程信息的接口。此外,在Linux 2.6.0-test6以上的版本中/proc/pid目录中有一个task目录,/proc/pid/task目录中也有一些以该进程所拥有的线程的线程号命名的目录/proc/pid/task/tid,它们是读取线程信息的接口。

    linux中的轻量级进程(lwp)即为线程,对应tid。

    计算某一个进程和某一个线程的cpu利用率,和计算系统的cpu利用率类似。读取/proc/pid/stat或者读取/proc/pid/task/stat中的参数来进行计算。

    3. cpu.load(系统平均负载,通过top、uptime、和falcon可以查看)

    系统平均负载被定义为在特定时间间隔内运行队列中(在CPU上运行或者等待运行多少进程)的平均进程数。如果一个进程满足以下条件则其就会位于运行队列中:

    • 它没有在等待I/O操作的结果

    • 它没有主动进入等待状态(也就是没有调用’wait’)

    • 没有被停止(例如:等待终止)

    在Linux中,进程分为三种状态,一种是阻塞的进程blocked process,一种是可运行的进程runnable process,另外就是正在运行的进程running process。

    进程可运行状态时,它处在一个运行队列run queue中,与其他可运行进程争夺CPU时间。 系统的load是指正在运行和准备好运行的进程的总数。比如现在系统有2个正在运行的进程,3个可运行进程,那么系统的load就是5。

    cpu.load是基于/proc/loadavg进行统计的。
    查看系统平均负载使用“cat /proc/loadavg”命令,输出结果如下:
    0.27 0.36 0.37 4/83 4828/
    前三个指1、5、15分钟内的平均进程数(可以简单理解为每五秒统计一次,其实真实计算比较复杂。https://blog.csdn.net/jlds123/article/details/7617132)。后面两个指(正在运行的进程数/进程总数)和最近运行的进程ID号。

    另外,通过"load average"中的三个数字,我们还可以了解到当前服务器的负载的变化趋势,如果1分钟的CPU负载 > 5分钟的CPU负载,说明服务器目前处在CPU负载高峰期;而如果1分钟的CPU负载 < 5分钟的CPU负载,则说明服务器的CPU负载高峰期刚刚过去了,如果是你处理了什么性能问题,则表明该处理已经显现成效了。

    cpu.load大于多少没有性能够问题呢?

    理想情况下cpu不空闲,但每个线程又都能及时获得cpu时间,没有等待的线程,任务处理完,紧接着出现另外一个可运行线程来获得cpu时间,此时cpu.load/cores=1。如果cpu.load过大则表示,有部分线程在等待获得cpu资源,过小表示cpu资源比较空闲。

    对于cpu.load多少开始出现性能问题,外界有不同的说法,有的认为cpu.load/cores最好不要超过1,有的认为cpu.load/cores最好不要超过3,有的认为cpu.load不超过2*cores-2即可。

    针对技术商服务进行压测时,发现load低时,接口TP999响应时间<50ms,而cpu.load/cores>4时,TP999响应时间约为200ms左右,多出来的时间可以理解为线程等待cpu处理的时间,可见cpu.load/cores过高时是影响接口响应时间的。

    因此可以结合预期的接口响应时间,来定义每个服务的cpu.load/cores不超过多少。比如要求接口响应时间尽可能快的,最好确保cpu.load/cores不超过1,而对时间敏感性要求不太高时,一般要求cpu.load/cores不超过3。

  • 相关阅读:
    Sqlite官方的查询优化文档
    VC++动态链接库(DLL)编程深入浅出(三)转
    用Python查询手机号码归属地
    Delphi使用迅雷的开放下载引擎下载
    Android基础之一
    VC++动态链接库深入浅出(转)
    在Python脚本中使用Delphi控件
    Python与其他语言结合的参数转换函数PyArg_ParseTuple()
    设计模式之模板方法模式(Template)
    设计模式之简单工厂模式(Simple Factory)
  • 原文地址:https://www.cnblogs.com/aspirant/p/9766992.html
Copyright © 2020-2023  润新知