2014-04-29 6 views
29

Es ist eine Frage, die oft gestellt wurde, aber es gibt keine gut unterstützte Antwort, die ich finden konnte.Genaue Berechnung der CPU-Auslastung in Prozent in Linux gegeben?

Viele Leute empfehlen die Verwendung von Top-Befehl, aber wenn Sie oben einmal ausführen (weil Sie ein Skript zum Beispiel cpu-Nutzung alle 1 Sekunde sammeln) gibt es immer die gleiche CPU-Nutzung Ergebnis (example 1, example 2).

Eine genauere Art und Weise der CPU-Auslastung zu berechnen, indem die Werte aus /proc/stat zu lesen, aber den meisten Antworten verwenden nur die ersten 4 Felder aus /proc/stat ihm zu berechnen (ein Beispiel here).

/proc/stat/ hat 10 Felder pro CPU-Kern ab Linux-Kernel 2.6.33!

Ich fand auch diese Accurately Calculating CPU Utilization in Linux using /proc/stat Frage, die auf das gleiche Problem hinweist, -dass die meisten anderen Fragen nur 4 aus den vielen Feldern in Betracht ziehen, aber die Antwort, die hier gegeben wird, beginnt mit "Ich denke" (nicht sicher) und betrifft nur die ersten 7 Felder (0 von 10 in /proc/stat/)

This Perl-Skript verwendet alle Felder, um die CPU-Auslastung zu berechnen, was ich nach einiger Zeit nicht mehr richtig finde Ermittlung.

Nach einem kurzen Blick in den Kernel-Code unter here, sieht es aus wie zum Beispiel guest_nice und guest fields immer steigen zusammen mit nice und user (also sollen sie nicht in der CPU-Auslastung Berechnung einbezogen werden, da sie enthalten sind in nice und user Felder bereits)

/* 
* 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; 
    } 
} 

So zusammenzufassen, was eine genaue Art und Weise ist die CPU-Auslastung in Linux zu berechnen und die in den Berechnungen und wie (die Felder zurückgeführt werden in den Ruhe betrachtet werden Felder sollen Zeit und welche Felder zu Nicht-Leerlaufzeit)?

+0

Der richtige Weg CPU-Auslastung Informationen zu sammeln kontinuierlich jede Sekunde zu laufen 'oben -b'. –

+0

Ich möchte Daten mit einem Drittanbieter-Skript sammeln und CPU ist nur eine der Metriken gesammelt werden müssen. Also würde ich gerne die CPU-Auslastung seit dem letzten Lauf (Intervall könnte variieren) dieses 3rd-Party-Skripts berechnen. 'top -b' läuft kontinuierlich, also muss es in einem separaten Thread laufen und die gesammelten Daten in einer anderen Ausgabe speichern. –

+0

Welche CPU-Auslastung suchen? Ein einzelner Prozess? Systemweit? Sollte es als Prozentsatz ausgedrückt werden, Sekunden, ...? – wallyk

Antwort

45

Nach dem htop Quellcode zum Zeitpunkt des Schreibens, sehen meine Annahmen wie sie gültig sind:

// 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; 

Und so, von den Feldern aufgelistet in dem ersten (void ProcessList_scan(ProcessList* this) Funktion bei ProcessList.c sehen) Linie /proc/stat: (siehe Abschnitt 1.8 bei documentation)

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

Algorithmisch, können wir die CPU-Auslastung Prozentsatz wie berechnen:

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 
+3

Ich möchte ein kleines Beispielprogramm teilen, das ich basierend auf dieser Antwort erstellt habe: https://github.com/scaidermern/top-processes. Fühlen Sie sich frei, uns davon zu machen, es ist unter CC0 lizenziert. – scai

+0

Ich denke, dass Iowait ein unterbrechungsfreier Zustand ist, also wäre es praktischer, ihn eher "geschäftlich" als untätig zu zählen. – wick

+0

guest und guest_nice sollte auch NonIdle nach diesem Beitrag hinzugefügt werden: https://unix.stackexchange.com/a/303224 –

3

Hey ich auch für das Thema recherchieren und fanden dieses Thema sehr hilfreich sein. Ich habe die Vangelis Tasoulas-Formel verwendet, um ein kleines Python-Skript dafür zu schreiben. Beigefügt ist mein Python-Code für das Problem. Es lädt die CPU-Nutzung pro CPU-ID jede Sekunde. Vielleicht hilft es anderen auch. Auch Kommentare/Vorschläge sind willkommen :-)

#!/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")     
2

Das folgende ist ein Bash-Skript, das auf Vangelis 'Antwort basiert.Es erzeugt eine Ausgabe wie folgt aus:

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

eine Datei get_cpu_usage.sh

Führen sie mit dem folgenden Befehl aufgerufen erstellen: bash get_cpu_usage.sh 0.2

Das Argument ist die Anzahl der Sekunden zu messen. In diesem Fall sind es 200 Millisekunden.

Die Inhalte sind:

#!/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