El programa My Go necesita conocer el porcentaje de uso de la CPU actual de todos los procesos del sistema y del usuario.Obtención de uso de CPU con golang
¿Cómo puedo obtener eso?
El programa My Go necesita conocer el porcentaje de uso de la CPU actual de todos los procesos del sistema y del usuario.Obtención de uso de CPU con golang
¿Cómo puedo obtener eso?
Tuve un problema similar y nunca encontré una implementación liviana. Aquí hay una versión reducida de mi solución que responde a su pregunta específica. Muestro el archivo /proc/stat
como lo recomienda tylerl. Notarás que espero 3 segundos entre las muestras para que coincida con la salida de la parte superior, pero también he tenido buenos resultados con 1 o 2 segundos. Ejecuto un código similar en un bucle dentro de una rutina ir, luego accedo al uso de la CPU cuando lo necesito de otras rutinas.
También puede analizar la salida de top -n1 | grep -i cpu
para obtener el uso de la CPU, pero solo muestra durante medio segundo en mi cuadro de Linux y estaba muy apagado durante la carga pesada. Regular la parte superior parecía coincidir muy de cerca cuando sincronizado y el siguiente programa:
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)
}
Parece como si se me permite enlazar a la plena aplicación que escribí en bitbucket; si no es así, siéntase libre de eliminar esto. Sin embargo, solo funciona en Linux hasta el momento: systemstat.go
Puede usar el paquete os.exec
para ejecutar el comando ps
y obtener el resultado.
Aquí es un programa de emisión de la orden ps aux
, analizar el resultado e imprimir el uso de la CPU de todos los procesos en 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")
}
}
Por favor, cuando invierte, tómese el tiempo para explicar por qué ... –
El análisis de cadenas desde una salida de comando no es una gran solución ya que el comando puede cambiar y también es pesado en cpu/mem/etc. –
@EricAnderson ¿Notaste que la respuesta aceptada (escrita más de un año después de la mía) hace lo mismo? ¿Elegiste responder solo al primero para brindar una solución a la pregunta? –
El mecanismo para conseguir uso de la CPU es OS-dependiente, ya que los números significan poco cosas diferentes a los diferentes núcleos del sistema operativo.
En Linux, puede consultar el kernel para obtener las últimas estadísticas leyendo los pseudo-archivos en el sistema de archivos /proc/
. Estos se generan sobre la marcha cuando los lee para reflejar el estado actual de la máquina.
Específicamente, el archivo /proc/<pid>/stat
para cada proceso contiene la información de contabilidad de proceso asociada. Está documentado en proc(5). Le interesan específicamente los campos utime
, stime
, cutime
y cstime
(comenzando en el campo 14).
Puede calcular el porcentaje con facilidad: simplemente lea los números, espere un intervalo de tiempo y léalos nuevamente. Tome la diferencia, divida por la cantidad de tiempo que esperó, y está su promedio. Esto es precisamente lo que hace el programa top
(así como también todos los demás programas que realizan el mismo servicio). Tenga en cuenta que puede tener más del 100% de uso de la CPU si tiene más de 1 CPU.
Si solo desea un resumen de todo el sistema, eso se informa en /proc/stat
- calcule su promedio con la misma técnica, pero solo tiene que leer un archivo.
Consulte este paquete http://github.com/c9s/goprocinfo, el paquete goprocinfo hace el análisis sintáctico para usted.
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
}
Excelente biblioteca, gracias. ¡Hace más que eso! – lzap
Aquí es una solución independiente OS utilizando Cgo para aprovechar la función clock() proporcionada por C standard library:
//#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
}
Puede simplificar 'time.Now(). Sub (startTime)' a 'time.Since (startTime)'. –
Gracias por la sugerencia, ejemplo actualizado. –
Nota: 'reloj()' da la hora del proceso actual solamente. –
recientemente que tenía que tomar mediciones de uso de la CPU de una frambuesa Pi (Raspbian OS) y se utiliza github.com/c9s/goprocinfo combinado con lo que se propone aquí:
La idea viene del código htop
origen y es tener dos mediciones (anterior/actual) con el fin de calcular el uso de la 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
}
Para más también se puede comprobar https://github.com/tgogos/rpi_cpu_memory
cuales idioma y sistema operativo que utiliza? –
Uso Go (de golang.org) en Linux, pero me gustaría usar algo portátil para otro * nix si es posible. –