Программа My Go должна знать процент использования текущего процессора для всех процессов системы и пользователя.
Как я могу это получить?
Программа My Go должна знать процент использования текущего процессора для всех процессов системы и пользователя.
Как я могу это получить?
У меня была аналогичная проблема, и я не нашел облегченной реализации. Вот небольшая версия моего решения, которая отвечает на ваш конкретный вопрос. Я читаю файл /proc/stat
так же, как рекомендует tylerl. Вы заметите, что я подождал 3 секунды между образцами, чтобы соответствовать верхнему результату, но у меня также были хорошие результаты с 1 или 2 секундами. Я запускаю аналогичный код в цикле в рамках подпрограммы go, а затем я обращаюсь к использованию процессора, когда мне это нужно, из других ходовых процедур.
Вы также можете разобрать вывод top -n1 | grep -i 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)
}
Кажется, мне позволено ссылаться на полную реализацию, которую я написал на битбакете; если нет, не стесняйтесь удалять это. Пока он работает только на linux: systemstat.go
Посмотрите этот пакет 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
}
Механизм получения использования ЦП зависит от ОС, поскольку цифры означают несколько разные вещи для разных ядер ОС.
В Linux вы можете запросить ядро, чтобы получить последнюю статистику, прочитав псевдофайлы в файловой системе /proc/
. Они генерируются "на лету", когда вы читаете их, чтобы отразить текущее состояние машины.
В частности, файл /proc/<pid>/stat
для каждого процесса содержит соответствующую информацию об учете процесса. Это описано в proc (5). Вас интересуют только поля utime
, stime
, cutime
и cstime
(начиная с 14-го поля).
Вы можете рассчитать процент достаточно легко: просто прочитайте цифры, подождите некоторое время и прочитайте их снова. Поймите разницу, разделите на количество времени, которое вы ждали, и там ваше среднее. Это как раз то, что делает программа top
(а также все другие программы, которые выполняют одну и ту же услугу). Имейте в виду, что вы можете использовать более 100% процессора, если у вас более 1 процессора.
Если вам просто нужна сводная информация об общей системе, указанная в /proc/stat
, - вычислите среднее значение по той же методике, но вам нужно прочитать только один файл.
Вы можете использовать пакет os.exec
для выполнения команды ps
и получить результат.
Вот программа, выдающая команду ps aux
, анализ результата и печать использования ЦП всех процессов в Linux:
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 для использования clock(), предоставляемой стандартной библиотекой C:
//#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
}
Недавно мне пришлось брать измерения использования процессора из малины Pi (Raspbian OS) и использовать github.com/c9s/goprocinfo в сочетании с тем, что предлагается здесь
Идея исходит из исходного кода htop
и должна иметь два измерения (предыдущий/текущий) для расчета использования ЦП:
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