在Linux中以百分比的forms精确计算CPU使用率?

这是一个多次被问到的问题,但是我没有find很好的答案。

许多人build议使用top命令,但是如果你只运行一次top(因为你有一个脚本例如每1秒收集一次cpu的使用情况),它总会给出相同的CPU使用结果( 例子1 , 例子2 )。

计算CPU使用率的更准确方法是读取/proc/stat ,但大多数答案仅使用/proc/stat的前4个字段来计算( 这里是一个示例)。

/proc/stat/在Linux内核2.6.33中每个CPU核心有10个字段!

我还发现, 在Linux中使用/ proc / stat问题准确地计算CPU利用率,这个问题指出了同样的问题 – 其他大多数问题只考虑了很多领域中的4个 – 但是这里给出的答案仍然以“I认为“(不确定),除了它只关心前7个字段( /proc/stat/的10个)

这个 perl脚本使用了所有的字段来计算CPU的使用情况,在我进一步调查之后,我不认为这是正确的。

在这里快速查看内核代码之后,看起来像guest_niceguest fields总是和niceuser一起增加(所以它们不应该包含在cpu使用计算中,因为它们包含在niceuser字段已经)

 /* * Account guest cpu time to a process. * @p: the process that the cpu time gets accounted to * @cputime: the cpu time spent in virtual machine since the last update * @cputime_scaled: cputime scaled by cpu frequency */ static void account_guest_time(struct task_struct *p, cputime_t cputime, cputime_t cputime_scaled) { u64 *cpustat = kcpustat_this_cpu->cpustat; /* Add guest time to process. */ p->utime += cputime; p->utimescaled += cputime_scaled; account_group_user_time(p, cputime); p->gtime += cputime; /* Add guest time to cpustat. */ if (task_nice(p) > 0) { cpustat[CPUTIME_NICE] += (__force u64) cputime; cpustat[CPUTIME_GUEST_NICE] += (__force u64) cputime; } else { cpustat[CPUTIME_USER] += (__force u64) cputime; cpustat[CPUTIME_GUEST] += (__force u64) cputime; } } 

因此,总结一下,计算Linux中CPU使用率的准确方法是什么,在计算中应该考虑哪些字段以及如何(哪些字段归因于空闲时间以及哪些字段为非空闲时间)?

Solutions Collecting From Web of "在Linux中以百分比的forms精确计算CPU使用率?"

根据撰写本文时的htop源代码,我的假设看起来像是有效的:

(请参阅void ProcessList_scan(ProcessList* this)

 // Guest time is already accounted in usertime usertime = usertime - guest; # As you see here, it subtracts guest from user time nicetime = nicetime - guestnice; # and guest_nice from nice time // Fields existing on kernels >= 2.6 // (and RHEL's patched kernel 2.4...) idlealltime = idletime + ioWait; # ioWait is added in the idleTime systemalltime = systemtime + irq + softIrq; virtalltime = guest + guestnice; totaltime = usertime + nicetime + systemalltime + idlealltime + steal + virtalltime; 

因此,从/proc/stat第一行中列出的字段(参见文档 1.8节)

  user nice system idle iowait irq softirq steal guest guest_nice cpu 74608 2520 24433 1117073 6176 4054 0 0 0 0 

算法上,我们可以计算CPU使用百分比,如下所示:

 PrevIdle = previdle + previowait Idle = idle + iowait PrevNonIdle = prevuser + prevnice + prevsystem + previrq + prevsoftirq + prevsteal NonIdle = user + nice + system + irq + softirq + steal PrevTotal = PrevIdle + PrevNonIdle Total = Idle + NonIdle # differentiate: actual value minus the previous one totald = Total - PrevTotal idled = Idle - PrevIdle CPU_Percentage = (totald - idled)/totald 

嘿,我也在研究这个话题,发现这个线程真的很有帮助。 我使用Vangelis Tasoulas公式来为此写一个小型的python脚本。 附件是我的Python代码的问题。 它每秒载入每个cpu_id的CPU使用量。 也许它也帮助别人。 也欢迎评论/建议:-)

 #!/usr/bin/python # -*- coding: utf-8 -*- ''' Created on 04.12.2014 @author: plagtag ''' from time import sleep import sys class GetCpuLoad(object): ''' classdocs ''' def __init__(self, percentage=True, sleeptime = 1): ''' @parent class: GetCpuLoad @date: 04.12.2014 @author: plagtag @info: @param: @return: CPU load in percentage ''' self.percentage = percentage self.cpustat = '/proc/stat' self.sep = ' ' self.sleeptime = sleeptime def getcputime(self): ''' http://stackoverflow.com/questions/23367857/accurate-calculation-of-cpu-usage-given-in-percentage-in-linux read in cpu information from file The meanings of the columns are as follows, from left to right: 0cpuid: number of cpu 1user: normal processes executing in user mode 2nice: niced processes executing in user mode 3system: processes executing in kernel mode 4idle: twiddling thumbs 5iowait: waiting for I/O to complete 6irq: servicing interrupts 7softirq: servicing softirqs #the formulas from htop user nice system idle iowait irq softirq steal guest guest_nice cpu 74608 2520 24433 1117073 6176 4054 0 0 0 0 Idle=idle+iowait NonIdle=user+nice+system+irq+softirq+steal Total=Idle+NonIdle # first line of file for all cpus CPU_Percentage=((Total-PrevTotal)-(Idle-PrevIdle))/(Total-PrevTotal) ''' cpu_infos = {} #collect here the information with open(self.cpustat,'r') as f_stat: lines = [line.split(self.sep) for content in f_stat.readlines() for line in content.split('\n') if line.startswith('cpu')] #compute for every cpu for cpu_line in lines: if '' in cpu_line: cpu_line.remove('')#remove empty elements cpu_line = [cpu_line[0]]+[float(i) for i in cpu_line[1:]]#type casting cpu_id,user,nice,system,idle,iowait,irq,softrig,steal,guest,guest_nice = cpu_line Idle=idle+iowait NonIdle=user+nice+system+irq+softrig+steal Total=Idle+NonIdle #update dictionionary cpu_infos.update({cpu_id:{'total':Total,'idle':Idle}}) return cpu_infos def getcpuload(self): ''' CPU_Percentage=((Total-PrevTotal)-(Idle-PrevIdle))/(Total-PrevTotal) ''' start = self.getcputime() #wait a second sleep(self.sleeptime) stop = self.getcputime() cpu_load = {} for cpu in start: Total = stop[cpu]['total'] PrevTotal = start[cpu]['total'] Idle = stop[cpu]['idle'] PrevIdle = start[cpu]['idle'] CPU_Percentage=((Total-PrevTotal)-(Idle-PrevIdle))/(Total-PrevTotal)*100 cpu_load.update({cpu: CPU_Percentage}) return cpu_load if __name__=='__main__': x = GetCpuLoad() while True: try: data = x.getcpuload() print data except KeyboardInterrupt: sys.exit("Finished") 

以下是一个基于Vangelis的回答的bash脚本。 它产生这样的输出:

 total 49.1803 cpu0 14.2857 cpu1 100 cpu2 28.5714 cpu3 100 cpu4 30 cpu5 25 

创建一个名为get_cpu_usage.sh的文件

使用以下命令运行它: bash get_cpu_usage.sh 0.2

参数是要测量的秒数。 在这种情况下,它是200毫秒。

内容是:

 #!/bin/sh sleepDurationSeconds=$1 previousDate=$(date +%s%N | cut -b1-13) previousStats=$(cat /proc/stat) sleep $sleepDurationSeconds currentDate=$(date +%s%N | cut -b1-13) currentStats=$(cat /proc/stat) cpus=$(echo "$currentStats" | grep -P 'cpu' | awk -F " " '{print $1}') for cpu in $cpus do currentLine=$(echo "$currentStats" | grep "$cpu ") user=$(echo "$currentLine" | awk -F " " '{print $2}') nice=$(echo "$currentLine" | awk -F " " '{print $3}') system=$(echo "$currentLine" | awk -F " " '{print $4}') idle=$(echo "$currentLine" | awk -F " " '{print $5}') iowait=$(echo "$currentLine" | awk -F " " '{print $6}') irq=$(echo "$currentLine" | awk -F " " '{print $7}') softirq=$(echo "$currentLine" | awk -F " " '{print $8}') steal=$(echo "$currentLine" | awk -F " " '{print $9}') guest=$(echo "$currentLine" | awk -F " " '{print $10}') guest_nice=$(echo "$currentLine" | awk -F " " '{print $11}') previousLine=$(echo "$previousStats" | grep "$cpu ") prevuser=$(echo "$previousLine" | awk -F " " '{print $2}') prevnice=$(echo "$previousLine" | awk -F " " '{print $3}') prevsystem=$(echo "$previousLine" | awk -F " " '{print $4}') previdle=$(echo "$previousLine" | awk -F " " '{print $5}') previowait=$(echo "$previousLine" | awk -F " " '{print $6}') previrq=$(echo "$previousLine" | awk -F " " '{print $7}') prevsoftirq=$(echo "$previousLine" | awk -F " " '{print $8}') prevsteal=$(echo "$previousLine" | awk -F " " '{print $9}') prevguest=$(echo "$previousLine" | awk -F " " '{print $10}') prevguest_nice=$(echo "$previousLine" | awk -F " " '{print $11}') PrevIdle=$((previdle + previowait)) Idle=$((idle + iowait)) PrevNonIdle=$((prevuser + prevnice + prevsystem + previrq + prevsoftirq + prevsteal)) NonIdle=$((user + nice + system + irq + softirq + steal)) PrevTotal=$((PrevIdle + PrevNonIdle)) Total=$((Idle + NonIdle)) totald=$((Total - PrevTotal)) idled=$((Idle - PrevIdle)) CPU_Percentage=$(awk "BEGIN {print ($totald - $idled)/$totald*100}") if [[ "$cpu" == "cpu" ]]; then echo "total "$CPU_Percentage else echo $cpu" "$CPU_Percentage fi done