打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
http://stackoverflow.com/questions/11356330/getting-cpu-usage-with-golang

My Go program needs to know the current cpu usage percentage of all system and user processes.

How can I obtain that?

asked Jul 6 '12 at 5:30
Sebastián Grignoli
10.7k74759
    
which language and OS you use? – Erdin? Ta?k?n Jul 6 '12 at 5:34
    
I use Go (from golang.org) under Linux, but I would like to use something portable to other *nix if it's possible. – Sebastián Grignoli Jul 6 '12 at 5:37

5 Answers

up vote 14 down vote accepted

I had a similar issue and never found a lightweight implementation. Here is a slimmed down version of my solution that answers your specific question. I sample the /proc/stat file just like tylerl recommends. You'll notice that I wait 3 seconds between samples to match top's output, but I have also had good results with 1 or 2 seconds. I run similar code in a loop within a go routine, then I access the cpu usage when I need it from other go routines.

You can also parse the output of top -n1 | grep -i cpu to get the cpu usage, but it only samples for half a second on my linux box and it was way off during heavy load. Regular top seemed to match very closely when I synchronized it and the following program:

package mainimport (    "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)}

It seems like I'm allowed to link to the full implementation that I wrote on bitbucket; if it's not, feel free to delete this. It only works on linux so far, though: systemstat.go

answered Jul 22 '13 at 9:12
bertimus9
16613

Check out this package http://github.com/c9s/goprocinfo, goprocinfo package does the parsing stuff for you.

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}
answered Nov 17 '13 at 17:20
c9s
863712
    
Excellent library, thanks. It does more than that! – lzap Feb 4 '14 at 14:50

The mechanism for getting CPU usage is OS-dependent, since the numbers mean slightly different things to different OS kernels.

On Linux, you can query the kernel to get the latest stats by reading the pseudo-files in the /proc/ filesystem. These are generated on-the-fly when you read them to reflect the current state of the machine.

Specifically, the /proc/<pid>/stat file for each process contains the associated process accounting information. It's documented in proc(5). You're interested specifically in fields utime, stime, cutime and cstime (starting at the 14th field).

You can calculate the percentage easily enough: just read the numbers, wait some time interval, and read them again. Take the difference, divide by the amount of time you waited, and there's your average. This is precisely what the top program does (as well as all other programs that perform the same service). Bear in mind that you can have over 100% cpu usage if you have more than 1 CPU.

If you just want a system-wide summary, that's reported in /proc/stat -- calculate your average using the same technique, but you only have to read one file.

answered Jul 6 '12 at 8:59
tylerl
17.7k75187

You can use the os.exec package to execute the ps command and get the result.

Here is a program issuing the ps aux command, parsing the result and printing the CPU usage of all processes on linux :

package mainimport (    "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")    }}
answered Jul 6 '12 at 7:35
Denys Séguret
188k21336396
2  
Please, when you downvote, take the time to explain why... – Denys Séguret Feb 8 '14 at 20:42
1  
String parsing from a command output is not a great solution as the command can change and it's also heavy on cpu/mem/etc. – Eric Anderson Aug 5 '14 at 15:23
    
@EricAnderson Did you notice the accepted answer (written more than one year after mine) does the same ? Did you choose to answer only the first one to provide a solution to the question ? – Denys Séguret Aug 5 '14 at 16:21
    
This is a good answer as it does work on Mac OS X 10.10 with just copy& paste (while the accepted answer doesn't) – Max Malysh May 18 at 10:48

Here is an OS independent solution using Cgo to harness the clock() function provided by 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}
answered Jun 24 at 15:28
1  
You could simplify time.Now().Sub(startTime) to time.Since(startTime). – Dave C Jun 24 at 16:21
    
Thanks for the suggestion, example updated. – Kyle Kloepper Jun 25 at 22:00
    
Sidenote: clock() gives the time of the current proccess only. – bohdan_trotsenko Nov 2 at 17:49
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
Get CPU Usage with GetSystemTimes
中华偏方 中药外敷治老年便秘验方 贵康网
大功率逆变电源制作
看過這個煎牛排知識圖片後,你也可以在家也可以吃到 5 星級廚師等級的牛排了! |
白启哲山水画艺术
囧知:爱因斯坦到底错哪儿了?
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服