簡體   English   中英

如何獲取 CPU 使用率

[英]How to get CPU usage

我的 Go 程序需要知道當前所有系統和用戶進程的 CPU 使用百分比。

我怎樣才能得到它?

查看這個包http://github.com/c9s/goprocinfo , goprocinfo 包為你做解析的東西。

stat, err := linuxproc.ReadStat("/proc/stat")
if err != nil {
    t.Fatal("stat read fail")
}

for _, s := range stat.CPUStats {
    // s.User
    // s.Nice
    // s.System
    // s.Idle
    // s.IOWait
}

我有一個類似的問題,但從未找到輕量級實現。 這是我的解決方案的精簡版,可以回答您的特定問題。 我像 tylerl 推薦的那樣對/proc/stat文件進行采樣。 您會注意到我在樣本之間等待 3 秒以匹配 top 的輸出,但我也有 1 或 2 秒的良好結果。 我在 go 例程中的循環中運行類似的代碼,然后在需要時從其他 go 例程訪問 cpu 使用情況。

您還可以解析top -n1 | grep -i cpu的輸出 top -n1 | grep -i cpu獲取 cpu 使用情況,但它僅在我的 linux 機器上采樣了半秒,並且在重負載期間它很遠。 當我將它與以下程序同步時,常規頂部似乎非常匹配:

package main

import (
    "fmt"
    "io/ioutil"
    "strconv"
    "strings"
    "time"
)

func getCPUSample() (idle, total uint64) {
    contents, err := ioutil.ReadFile("/proc/stat")
    if err != nil {
        return
    }
    lines := strings.Split(string(contents), "\n")
    for _, line := range(lines) {
        fields := strings.Fields(line)
        if fields[0] == "cpu" {
            numFields := len(fields)
            for i := 1; i < numFields; i++ {
                val, err := strconv.ParseUint(fields[i], 10, 64)
                if err != nil {
                    fmt.Println("Error: ", i, fields[i], err)
                }
                total += val // tally up all the numbers to get total ticks
                if i == 4 {  // idle is the 5th field in the cpu line
                    idle = val
                }
            }
            return
        }
    }
    return
}

func main() {
    idle0, total0 := getCPUSample()
    time.Sleep(3 * time.Second)
    idle1, total1 := getCPUSample()

    idleTicks := float64(idle1 - idle0)
    totalTicks := float64(total1 - total0)
    cpuUsage := 100 * (totalTicks - idleTicks) / totalTicks

    fmt.Printf("CPU usage is %f%% [busy: %f, total: %f]\n", cpuUsage, totalTicks-idleTicks, totalTicks)
}

似乎我被允許鏈接到我在 bitbucket 上寫的完整實現; 如果不是,請隨意刪除它。 不過,它目前只適用於 linux: systemstat.go

獲取 CPU 使用率的機制取決於操作系統,因為這些數字對不同的操作系統內核的含義略有不同。

在 Linux 上,您可以通過讀取/proc/文件系統中的偽文件來查詢內核以獲取最新的統計信息。 這些是在您閱讀它們以反映機器的當前狀態時即時生成的。

具體來說,每個進程的/proc/<pid>/stat文件包含相關的進程記帳信息。 它記錄在proc(5) 中 您對utimestimecutimecstime字段utime cstime (從第 14 個字段開始)。

您可以很容易地計算百分比:只需讀取數字,等待一段時間間隔,然后再次讀取它們。 取差值,除以您等待的時間,就是您的平均值。 這正是top程序所做的(以及執行相同服務的所有其他程序)。 請記住,如果您有 1 個以上的 CPU,則 CPU 使用率可能會超過 100%。

如果您只想要一個系統范圍的摘要,那么它會在/proc/stat報告——使用相同的技術計算您的平均值,但您只需閱讀一個文件。

您可以使用os.exec包執行ps命令並獲取結果。

這是一個發出ps aux命令的程序,解析結果並打印 linux 上所有進程的 CPU 使用率:

package main

import (
    "bytes"
    "log"
    "os/exec"
    "strconv"
    "strings"
)

type Process struct {
    pid int
    cpu float64
}

func main() {
    cmd := exec.Command("ps", "aux")
    var out bytes.Buffer
    cmd.Stdout = &out
    err := cmd.Run()
    if err != nil {
        log.Fatal(err)
    }
    processes := make([]*Process, 0)
    for {
        line, err := out.ReadString('\n')
        if err!=nil {
            break;
        }
        tokens := strings.Split(line, " ")
        ft := make([]string, 0)
        for _, t := range(tokens) {
            if t!="" && t!="\t" {
                ft = append(ft, t)
            }
        }
        log.Println(len(ft), ft)
        pid, err := strconv.Atoi(ft[1])
        if err!=nil {
            continue
        }
        cpu, err := strconv.ParseFloat(ft[2], 64)
        if err!=nil {
            log.Fatal(err)
        }
        processes = append(processes, &Process{pid, cpu})
    }
    for _, p := range(processes) {
        log.Println("Process ", p.pid, " takes ", p.cpu, " % of the CPU")
    }
}

這是一個獨立於操作系統的解決方案,它使用Cgo來利用C 標准庫提供的clock()函數:

//#include <time.h>
import "C"
import "time"

var startTime = time.Now()
var startTicks = C.clock()

func CpuUsagePercent() float64 {
    clockSeconds := float64(C.clock()-startTicks) / float64(C.CLOCKS_PER_SEC)
    realSeconds := time.Since(startTime).Seconds()
    return clockSeconds / realSeconds * 100
}

我最近不得不從 Raspberry Pi(Raspbian 操作系統)進行 CPU 使用率測量,並使用github.com/c9s/goprocinfo結合這里提出的內容:

這個想法來自htop源代碼,並且有兩個測量值(以前的/當前的)來計算 CPU 使用率:

func calcSingleCoreUsage(curr, prev linuxproc.CPUStat) float32 {

  PrevIdle := prev.Idle + prev.IOWait
  Idle := curr.Idle + curr.IOWait

  PrevNonIdle := prev.User + prev.Nice + prev.System + prev.IRQ + prev.SoftIRQ + prev.Steal
  NonIdle := curr.User + curr.Nice + curr.System + curr.IRQ + curr.SoftIRQ + curr.Steal

  PrevTotal := PrevIdle + PrevNonIdle
  Total := Idle + NonIdle
  // fmt.Println(PrevIdle, Idle, PrevNonIdle, NonIdle, PrevTotal, Total)

  //  differentiate: actual value minus the previous one
  totald := Total - PrevTotal
  idled := Idle - PrevIdle

  CPU_Percentage := (float32(totald) - float32(idled)) / float32(totald)

  return CPU_Percentage
}

有關更多信息,您還可以查看https://github.com/tgogos/rpi_cpu_memory

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM