40

My Goプログラムは、すべてのシステムおよびユーザープロセスの現在のCPU使用率を知る必要があります。

どうすれば入手できますか?

4

6 に答える 6

33

このパッケージ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
}
于 2013-11-17T17:20:51.787 に答える
28

私も同様の問題を抱えていましたが、軽量の実装は見つかりませんでした。これが私のソリューションのスリム化されたバージョンで、あなたの特定の質問に答えます。/proc/stattylerlが推奨するようにファイルをサンプリングします。サンプル間でトップの出力と一致するまで3秒待つことに気付くでしょうが、1秒または2秒でも良い結果が得られています。同様のコードをgoルーチン内のループで実行し、他のgoルーチンから必要なときにCPU使用率にアクセスします。

の出力を解析しtop -n1 | grep -i cpuてCPU使用率を取得することもできますが、私のLinuxボックスでは0.5秒間しかサンプリングされておらず、高負荷時にはかなりオフになりました。通常のトップは、それと次のプログラムを同期したときに非常によく一致しているように見えました。

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

于 2013-07-22T09:12:43.690 に答える
19

CPU使用率を取得するメカニズムは、OSに依存します。これは、数値がOSカーネルごとにわずかに異なることを意味するためです。

Linuxでは、ファイルシステム内の疑似ファイルを読み取ることにより、カーネルにクエリを実行して最新の統計を取得でき/proc/ます。これらは、マシンの現在の状態を反映するために読み取るときにオンザフライで生成されます。

具体的には、/proc/<pid>/stat各プロセスのファイルには、関連するプロセスアカウンティング情報が含まれています。proc(5)に記載されています。utime特にフィールド、、、および(14番目のフィールドから)にstime関心があります。cutimecstime

パーセンテージは簡単に計算できます。数値を読み取り、一定の時間間隔を待ってから、もう一度読み取ります。差を取り、あなたが待った時間で割ると、あなたの平均があります。これはまさにtopプログラムが行うことです(そして同じサービスを実行する他のすべてのプログラムも同様です)。CPUが複数ある場合は、CPU使用率が100%を超える可能性があることに注意してください。

システム全体の要約が必要な場合は、-で報告され/proc/statます。同じ手法を使用して平均を計算しますが、1つのファイルを読み取るだけで済みます。

于 2012-07-06T08:59:04.427 に答える
15

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")
    }
}
于 2012-07-06T07:35:22.627 に答える
8

これは、 Cgoを使用してC標準ライブラリによって提供されるclock()関数を利用するOSに依存しないソリューションです。

//#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
}
于 2015-06-24T15:28:53.483 に答える
2

最近、Raspberry Pi(Raspbian OS)からCPU使用率を測定する必要があり、github.com / c9s/goprocinfoをここで提案されているものと組み合わせて使用​​しました。

アイデアはhtopソースコードから来ており、CPU使用率を計算するために2つの測定値(以前/現在)を取得することです。

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を確認することもできます

于 2017-02-02T15:55:29.230 に答える