From ead83931379acfb1e6d092662ef1c0bd0d3b5da4 Mon Sep 17 00:00:00 2001 From: WAKAYAMA Shirou Date: Wed, 11 Mar 2015 23:00:06 +0900 Subject: [PATCH] cpu: use wmic to get CPU usage on Windows. --- cpu/cpu.go | 56 ++--------------------------- cpu/cpu_test.go | 5 ++- cpu/cpu_unix.go | 90 ++++++++++++++++++++++++++++++++++++++++++++++ cpu/cpu_windows.go | 23 ++++++++++++ 4 files changed, 119 insertions(+), 55 deletions(-) create mode 100644 cpu/cpu_unix.go diff --git a/cpu/cpu.go b/cpu/cpu.go index 06999a2e..b8e8edb4 100644 --- a/cpu/cpu.go +++ b/cpu/cpu.go @@ -5,7 +5,6 @@ import ( "runtime" "strconv" "strings" - "time" ) type CPUTimesStat struct { @@ -38,62 +37,11 @@ type CPUInfoStat struct { Flags []string `json:"flags"` } -func CPUCounts(logical bool) (int, error) { - return runtime.NumCPU(), nil -} - var lastCPUTimes []CPUTimesStat var lastPerCPUTimes []CPUTimesStat -func CPUPercent(interval time.Duration, percpu bool) ([]float64, error) { - getAllBusy := func(t CPUTimesStat) (float64, float64) { - busy := t.User + t.System + t.Nice + t.Iowait + t.Irq + - t.Softirq + t.Steal + t.Guest + t.GuestNice + t.Stolen - return busy + t.Idle, busy - } - - calculate := func(t1, t2 CPUTimesStat) float64 { - t1All, t1Busy := getAllBusy(t1) - t2All, t2Busy := getAllBusy(t2) - - if t2Busy <= t1Busy { - return 0 - } - if t2All <= t1All { - return 1 - } - return (t2Busy - t1Busy) / (t2All - t1All) * 100 - } - - cpuTimes, err := CPUTimes(percpu) - if err != nil { - return nil, err - } - - if interval > 0 { - if !percpu { - lastCPUTimes = cpuTimes - } else { - lastPerCPUTimes = cpuTimes - } - time.Sleep(interval) - cpuTimes, err = CPUTimes(percpu) - if err != nil { - return nil, err - } - } - - ret := make([]float64, len(cpuTimes)) - if !percpu { - ret[0] = calculate(lastCPUTimes[0], cpuTimes[0]) - lastCPUTimes = cpuTimes - } else { - for i, t := range cpuTimes { - ret[i] = calculate(lastPerCPUTimes[i], t) - } - lastPerCPUTimes = cpuTimes - } - return ret, nil +func CPUCounts(logical bool) (int, error) { + return runtime.NumCPU(), nil } func (c CPUTimesStat) String() string { diff --git a/cpu/cpu_test.go b/cpu/cpu_test.go index 1518fda6..7de17a76 100644 --- a/cpu/cpu_test.go +++ b/cpu/cpu_test.go @@ -63,7 +63,10 @@ func TestCpuInfo(t *testing.T) { func testCPUPercent(t *testing.T, percpu bool) { numcpu := runtime.NumCPU() + testCount := 3 + if runtime.GOOS != "windows" { + testCount = 100 v, err := CPUPercent(time.Millisecond, percpu) if err != nil { t.Errorf("error %v", err) @@ -72,7 +75,7 @@ func testCPUPercent(t *testing.T, percpu bool) { t.Fatalf("wrong number of entries from CPUPercent: %v", v) } } - for i := 0; i < 100; i++ { + for i := 0; i < testCount; i++ { duration := time.Duration(10) * time.Microsecond v, err := CPUPercent(duration, percpu) if err != nil { diff --git a/cpu/cpu_unix.go b/cpu/cpu_unix.go new file mode 100644 index 00000000..4871fcd8 --- /dev/null +++ b/cpu/cpu_unix.go @@ -0,0 +1,90 @@ +// +build linux,freebsd,darwin + +package cpu + +import ( + "encoding/json" + "strconv" + "strings" + "time" +) + +func CPUPercent(interval time.Duration, percpu bool) ([]float64, error) { + getAllBusy := func(t CPUTimesStat) (float64, float64) { + busy := t.User + t.System + t.Nice + t.Iowait + t.Irq + + t.Softirq + t.Steal + t.Guest + t.GuestNice + t.Stolen + return busy + t.Idle, busy + } + + calculate := func(t1, t2 CPUTimesStat) float64 { + t1All, t1Busy := getAllBusy(t1) + t2All, t2Busy := getAllBusy(t2) + + if t2Busy <= t1Busy { + return 0 + } + if t2All <= t1All { + return 1 + } + return (t2Busy - t1Busy) / (t2All - t1All) * 100 + } + + cpuTimes, err := CPUTimes(percpu) + if err != nil { + return nil, err + } + + if interval > 0 { + if !percpu { + lastCPUTimes = cpuTimes + } else { + lastPerCPUTimes = cpuTimes + } + time.Sleep(interval) + cpuTimes, err = CPUTimes(percpu) + if err != nil { + return nil, err + } + } + + ret := make([]float64, len(cpuTimes)) + if !percpu { + ret[0] = calculate(lastCPUTimes[0], cpuTimes[0]) + lastCPUTimes = cpuTimes + } else { + for i, t := range cpuTimes { + ret[i] = calculate(lastPerCPUTimes[i], t) + } + lastPerCPUTimes = cpuTimes + } + return ret, nil +} + +func (c CPUTimesStat) String() string { + v := []string{ + `"cpu":"` + c.CPU + `"`, + `"user":` + strconv.FormatFloat(c.User, 'f', 1, 64), + `"system":` + strconv.FormatFloat(c.System, 'f', 1, 64), + `"idle":` + strconv.FormatFloat(c.Idle, 'f', 1, 64), + `"nice":` + strconv.FormatFloat(c.Nice, 'f', 1, 64), + `"iowait":` + strconv.FormatFloat(c.Iowait, 'f', 1, 64), + `"irq":` + strconv.FormatFloat(c.Irq, 'f', 1, 64), + `"softirq":` + strconv.FormatFloat(c.Softirq, 'f', 1, 64), + `"steal":` + strconv.FormatFloat(c.Steal, 'f', 1, 64), + `"guest":` + strconv.FormatFloat(c.Guest, 'f', 1, 64), + `"guest_nice":` + strconv.FormatFloat(c.GuestNice, 'f', 1, 64), + `"stolen":` + strconv.FormatFloat(c.Stolen, 'f', 1, 64), + } + + return `{` + strings.Join(v, ",") + `}` +} + +func (c CPUInfoStat) String() string { + s, _ := json.Marshal(c) + return string(s) +} + +func init() { + lastCPUTimes, _ = CPUTimes(false) + lastPerCPUTimes, _ = CPUTimes(true) +} diff --git a/cpu/cpu_windows.go b/cpu/cpu_windows.go index 41f00544..0980aa06 100644 --- a/cpu/cpu_windows.go +++ b/cpu/cpu_windows.go @@ -6,6 +6,7 @@ import ( "strconv" "strings" "syscall" + "time" "unsafe" common "github.com/shirou/gopsutil/common" @@ -79,3 +80,25 @@ func CPUInfo() ([]CPUInfoStat, error) { } return ret, nil } + +func CPUPercent(interval time.Duration, percpu bool) ([]float64, error) { + ret := []float64{} + + lines, err := common.GetWmic("cpu", "loadpercentage") + if err != nil { + return ret, err + } + for _, l := range lines { + t := strings.Split(l, ",") + + if len(t) < 2 { + continue + } + p, err := strconv.Atoi(t[1]) + if err != nil { + p = 0 + } + ret = append(ret, float64(p)/100.0) + } + return ret, nil +}