2014-04-29 9 views
29

यह एक प्रश्न है जिसे कई बार पूछा गया है, हालांकि मुझे कोई अच्छा समर्थन नहीं मिला है।लिनक्स में प्रतिशत में दिए गए CPU उपयोग की सटीक गणना?

कई लोग शीर्ष आदेश का उपयोग करने का सुझाव देते हैं, लेकिन यदि आप एक बार शीर्ष पर दौड़ते हैं (क्योंकि आपके पास प्रत्येक 1 सेकंड में सीपीयू उपयोग एकत्र करने के लिए एक स्क्रिप्ट है) तो यह हमेशा एक ही सीपीयू उपयोग परिणाम (example 1, example 2) प्रदान करेगा।

CPU उपयोग गणना करने के लिए एक अधिक सटीक तरीका, /proc/stat से मूल्यों को पढ़ने के द्वारा होता है, लेकिन उत्तर के सबसे केवल /proc/stat से पहले 4 क्षेत्रों में यह (एक उदाहरण here) की गणना करने का उपयोग करें।

/proc/stat/ में 10 फ़ील्ड प्रति सीपीयू कोर लिनक्स कर्नेल 2.6.33 के रूप में है!

मुझे यह भी Accurately Calculating CPU Utilization in Linux using /proc/stat प्रश्न मिला जो एक ही मुद्दे को इंगित कर रहा है, लेकिन अधिकांश अन्य प्रश्न केवल कई क्षेत्रों में से 4 को ध्यान में रखते हैं- लेकिन फिर भी यहां दिया गया उत्तर "मुझे लगता है" (निश्चित नहीं) से शुरू होता है , और इसके अलावा, यह केवल पहले 7 फ़ील्ड (/proc/stat/ में 10 में से) के बारे में चिंतित है)

This perl स्क्रिप्ट सीपीयू उपयोग की गणना करने के लिए सभी क्षेत्रों का उपयोग करता है, जो मुझे लगता है कि कुछ और के बाद सही नहीं है जाँच पड़ताल।

कर्नेल कोड here में शीघ्रता से अवलोकन करने के बाद, ऐसा लगता है, जैसे उदाहरण के लिए, guest_nice और guest fields हमेशा एक साथ nice और user साथ (ताकि वे CPU उपयोग गणना में शामिल नहीं किया जाना चाहिए बढ़ रही हैं, क्योंकि वे शामिल किए गए हैं पहले से ही nice और user क्षेत्रों)

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

में तो योग करने के लिए, लिनक्स में CPU उपयोग गणना करने के लिए एक सटीक तरीका है क्या और खेतों जो गणना और कैसे में विचार किया जाना चाहिए (जो खेतों निष्क्रिय करने के लिए जिम्मेदार ठहराया जाता है समय और कौन सा क्षेत्र गैर-निष्क्रिय समय के लिए)?

+0

सही तरीके से CPU उपयोग जानकारी हर दूसरे 'शीर्ष चलाने के लिए -b' लगातार है इकट्ठा करने के लिए। –

+0

मैं किसी तृतीय पक्ष स्क्रिप्ट का उपयोग करके डेटा एकत्र करना चाहता हूं और सीपीयू केवल मेट्रिक्स में से एक है जिसे एकत्रित करने की आवश्यकता है। इसलिए मैं इस तीसरे पक्ष की स्क्रिप्ट के पिछले रन (अंतराल भिन्न हो सकता है) के बाद से CPU उपयोग की गणना करना चाहता हूं। 'टॉप-बी' लगातार चलता है, इसलिए इसे एक अलग थ्रेड में चलाया जाता है और एकत्रित डेटा को एक अलग आउटपुट में सहेजना पड़ता है। –

+0

क्या सीपीयू उपयोग की तलाश है? एक प्रक्रिया? प्रणाली विस्तृत? इसे प्रतिशत, सेकंड, ... के रूप में व्यक्त किया जाना चाहिए? – wallyk

उत्तर

45

अनुसार लेखन के समय htop स्रोत कोड, मेरी मान्यताओं लगता है कि वे मान्य हैं:

(ProcessList.c पर 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 की लाइन: (documentation पर खंड 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 
+3

मैं इस उत्तर के आधार पर बनाया गया एक छोटा सा उदाहरण प्रोग्राम साझा करना चाहता हूं: https://github.com/scaidermern/top-processes। हमें इसे बनाने के लिए स्वतंत्र महसूस करें, इसे CC0 के तहत लाइसेंस प्राप्त है। – scai

+0

मुझे लगता है कि iowait एक निर्बाध स्थिति है, इसलिए निष्क्रिय होने के बजाय इसे "व्यवसाय" में गिनना अधिक व्यावहारिक होगा। – wick

+0

अतिथि और guest_nice को इस पोस्ट के अनुसार NonIdle में भी जोड़ा जाना चाहिए: https://unix.stackexchange.com/a/303224 –

3

अरे मैं भी विषय के लिए शोध किया गया था और इस सूत्र वास्तव में उपयोगी पाया। मैंने इसके लिए एक छोटी पायथन लिपि लिखने के लिए वेंजेलीस तसोउला सूत्र का उपयोग किया। इस मुद्दे के लिए मेरे पायथन कोड संलग्न है। यह प्रत्येक सेकेंड प्रति 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")     
2

निम्नलिखित एक bash स्क्रिप्ट जो Vangelis के जवाब पर आधारित है।यह इस तरह से उत्पादन का उत्पादन: bash get_cpu_usage.sh 0.2

तर्क को मापने के लिए सेकंड की संख्या है:

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

एक फ़ाइल बुलाया get_cpu_usage.sh

भागो यह निम्न आदेश का उपयोग कर बनाएँ। इस मामले में यह 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 
संबंधित मुद्दे