LINUX性能量化之CPU

CPU数量

物理cpu个数:

$ cat /proc/cpuinfo | grep "physical id" | sort | uniq | wc -l
2

cpu core的个数:

$ cat /proc/cpuinfo | grep "cpu cores" | uniq -c
16 cpu cores       : 4

逻辑cpu的个数:

$ cat /proc/cpuinfo | grep "siblings" | uniq
siblings        : 8

LOAD

其实load的指标反映的是进程的排队情况,也就是当cpu的处理能力不足的时候,进程会在运行的队列里进行排队,等待cpu时间,当系统的任务过多,cpu处理能力不足的时候,load就会显著的升高。

先了解下进程的状态,如下图:


image.png

从使用系统调用fork()创建一个进程到进程从进程表中删除,进程会经历多种的状态,在上图显示了六种状态,分表是:

  1. executing in user mode
  2. executing in kernel mode
  3. ready to run
  4. sleeping
  5. newly created, not ready to run, and not sleeping
  6. issued exit system call (zombie)

一个进程的生命周期可以描述为:

首先会调用fork()来创建一个进程,然后当exec()的时候,并不是就分配了cpu,因为cpu的分配有多种方式,比如抢占式,时间片轮询等,所以这时进程会进入准备队列,即就绪状态,随时都可以执行。

当进程获得cpu时间的时候,进程会进入状态1(running in user mode),这时也会因为system clock的原因而重新又进入准备队列中。

比如进程要读取操作系统文件的内容,那么将发起一个系统调用read(),进程进入状态2(running in kernel mode),然后cpu将执行os的服务程序,这里执行的其实就是硬盘控制器的驱动程序,执行完成后,进程进入状态4(sleeping)。

驱动程序其实是发送的硬盘控制器的指令,硬盘控制器接受到指令后,开始从硬盘上读取数据,这时进程一直处在sleeping的状态,等数据准备完成之后,硬盘控制器将发送一个中断指令,cpu接受到中断后,进入中断服务处理程序,拷贝数据到内存中,然后进程被唤醒,从新进入就绪状态。

当进程显示的调用exit()时,系统调用将释放进程使用的数据结构,但进程表中的slot还保留着,因为这块区域是exit的代码区域,父进程需要根据它来判断是否正常exit,这时进程进入状态6(zombie),这时进程除了process table里的一些内容外,没有了其它任何东西,所以也没有办法kill这个进程,这个时候只能等待系统来清理。
查看当前系统的load:

$ cat /proc/loadavg 
1.73 2.10 1.96 3/2569 866

参数的解释是:

avg_1 (1.73) 1-分钟平均负载
lavg_5 (2.10) 5-分钟平均负载
lavg_15(1.96) 15-分钟平均负载
nr_running (3) 在采样时刻,运行队列的任务的数目
nr_threads (2569) 在采样时刻,系统中活跃的任务的个数(不包括运行已经结束的任务)
last_pid(866) 最大的pid值,包括轻量级进程,即线程
如果当前系统有两个cpu,那么每颗cpu的的运行队列长度就是1.73/2=0.86。

对于load的值,如果恰好等于系统的cpu的个数,说明没有排队的现象,cpu的处理能力刚好能够处理当前的任务,如果load除以cpu的个数大于5的话,就说明排队的现象比较严重,cpu就开始成为系统的瓶颈了。

CPU利用率的计算

$ cat /proc/stat 
cpu  1328826685 9908 956723151 37475308887 385172562 1674680 40475782
cpu0 410951159 118 270447961 1807752465 3995607 1256760 17354845
cpu1 87245025 2055 64833801 2348250538 9854553 51903 1531320
cpu2 72781822 257 61529788 2352243761 22342448 9670 2855194
cpu3 46745786 1206 44133270 2248648260 170037161 69330 2128288
cpu4 123440853 1554 31290213 2341183797 13100817 84271 2656769
cpu5 36306470 620 11485132 2460075134 3238150 39536 624727
cpu6 56711524 8 60381304 2390770657 2721730 1 1174918
cpu7 35676024 46 84850159 2356783851 33411961 0 1038483
cpu8 99217709 166 22269812 2386700351 2648336 46 921814
cpu9 35316582 71 9077959 2465760121 1396419 0 218414
cpu10 55429624 5 58736923 2393997677 2403804 0 1190020
cpu11 36376053 127 91350249 2353554118 29403857 2 1075565
cpu12 94113797 2498 20676353 2381646886 13099910 86996 2131685
cpu13 35960873 644 11974688 2451183596 11241526 31587 1376153
cpu14 64988644 65 47646699 2371237606 24944343 15514 2924129
cpu15 37564733 461 66038834 2365520062 41331934 29056 1273450
intr 32192598678 3652207391 10 0 6 6 0 0 0 0 150 0 0 65 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 41 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1169002395 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 961594445 0 0 0 0 0 0 0 3774974 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3762233747 0 0 0 0 0 0 0 1168948909 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 60 0 0 0 0 0
ctxt 74186330107
btime 1286108830
processes 76903816
procs_running 4
procs_blocked 0

user (1328826685) 从系统启动开始累计到当前时刻,用户态的CPU时间(单位:jiffies) ,不包含 nice值为负进程。1jiffies=0.01秒
nice (9908) 从系统启动开始累计到当前时刻,nice值为负的进程所占用的CPU时间(单位:jiffies)
system (956723151) 从系统启动开始累计到当前时刻,核心时间(单位:jiffies)
idle (37475308887) 从系统启动开始累计到当前时刻,除硬盘IO等待时间以外其它等待时间(单位:jiffies)
iowait (385172562) 从系统启动开始累计到当前时刻,硬盘IO等待时间(单位:jiffies) ,
irq (1674680) 从系统启动开始累计到当前时刻,硬中断时间(单位:jiffies)
softirq (40475782) 从系统启动开始累计到当前时刻,软中断时间(单位:jiffies)
CPU时间=user+system+nice+idle+iowait+irq+softirq

“intr”这行给出中断的信息,第一个为自系统启动以来,发生的所有的中断的次数;然后每个数对应一个特定的中断自系统启动以来所发生的次数。
“ctxt”给出了自系统启动以来CPU发生的上下文交换的次数。
“btime”给出了从系统启动到现在为止的时间,单位为秒。
“processes (total_forks) 自系统启动以来所创建的任务的个数目。
“procs_running”:当前运行队列的任务的数目。
“procs_blocked”:当前被阻塞的任务的数目。

统计CPU使用率脚本:

#!/bin/bash
interval=3
cpu_num=`cat /proc/stat | grep cpu[0-9] -c`

start_idle=()
start_total=()
cpu_rate=()

cpu_rate_file=./`hostname`_cpu_rate.csv
if [ -f ${cpu_rate_file} ]; then
    mv ${cpu_rate_file} ${cpu_rate_file}.`date +%m_%d-%H_%M_%S`.bak
fi
for((i=0;i<${cpu_num};i++))
{
    echo -n "cpu$i," >> ${cpu_rate_file}
}
echo -n "cpu_avg" >> ${cpu_rate_file}
echo "" >> ${cpu_rate_file}

while(true)
do
    for((i=0;i<${cpu_num};i++))
    {
        start=$(cat /proc/stat | grep "cpu$i" | awk '{print $2" "$3" "$4" "$5" "$6" "$7" "$8}')
        start_idle[$i]=$(echo ${start} | awk '{print $4}')
        start_total[$i]=$(echo ${start} | awk '{printf "%.f",$1+$2+$3+$4+$5+$6+$7}')
    }
    start=$(cat /proc/stat | grep "cpu " | awk '{print $2" "$3" "$4" "$5" "$6" "$7" "$8}')
    start_idle[${cpu_num}]=$(echo ${start} | awk '{print $4}')
    start_total[${cpu_num}]=$(echo ${start} | awk '{printf "%.f",$1+$2+$3+$4+$5+$6+$7}')
    sleep ${interval}
    for((i=0;i<${cpu_num};i++))
    {
        end=$(cat /proc/stat | grep "cpu$i" | awk '{print $2" "$3" "$4" "$5" "$6" "$7" "$8}')
        end_idle=$(echo ${end} | awk '{print $4}')
        end_total=$(echo ${end} | awk '{printf "%.f",$1+$2+$3+$4+$5+$6+$7}')
        idle=`expr ${end_idle} - ${start_idle[$i]}`
        total=`expr ${end_total} - ${start_total[$i]}`
        idle_normal=`expr ${idle} \* 100`
        cpu_usage=`expr ${idle_normal} / ${total}`
        cpu_rate[$i]=`expr 100 - ${cpu_usage}`
        echo "The CPU$i Rate : ${cpu_rate[$i]}%"
        echo -n "${cpu_rate[$i]}," >> ${cpu_rate_file}
    }
    end=$(cat /proc/stat | grep "cpu " | awk '{print $2" "$3" "$4" "$5" "$6" "$7" "$8}')
    end_idle=$(echo ${end} | awk '{print $4}')
    end_total=$(echo ${end} | awk '{printf "%.f",$1+$2+$3+$4+$5+$6+$7}')
    idle=`expr ${end_idle} - ${start_idle[$i]}`
    total=`expr ${end_total} - ${start_total[$i]}`
    idle_normal=`expr ${idle} \* 100`
    cpu_usage=`expr ${idle_normal} / ${total}`
    cpu_rate[${cpu_num}]=`expr 100 - ${cpu_usage}`
    echo "The Average CPU Rate : ${cpu_rate[${cpu_num}]}%"
    echo -n "${cpu_rate[${cpu_num}]}" >> ${cpu_rate_file}
    echo "------------------"
    echo "" >> ${cpu_rate_file}
done
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容