Skip to content

Commit

Permalink
cpu.Percent (Windows): Use the same implementation as on Unix
Browse files Browse the repository at this point in the history
WMI is way too slow.
  • Loading branch information
hillu committed Sep 27, 2016
1 parent af2b512 commit 832dcb9
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 109 deletions.
83 changes: 83 additions & 0 deletions cpu/cpu.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ package cpu

import (
"encoding/json"
"fmt"
"runtime"
"strconv"
"strings"
"sync"
"time"

"github.com/shirou/gopsutil/internal/common"
)
Expand Down Expand Up @@ -91,3 +93,84 @@ func (c InfoStat) String() string {
s, _ := json.Marshal(c)
return string(s)
}

func getAllBusy(t TimesStat) (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
}

func calculateBusy(t1, t2 TimesStat) 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
}

func calculateAllBusy(t1, t2 []TimesStat) ([]float64, error) {
// Make sure the CPU measurements have the same length.
if len(t1) != len(t2) {
return nil, fmt.Errorf(
"received two CPU counts: %d != %d",
len(t1), len(t2),
)
}

ret := make([]float64, len(t1))
for i, t := range t2 {
ret[i] = calculateBusy(t1[i], t)
}
return ret, nil
}

//Percent calculates the percentage of cpu used either per CPU or combined.
//If an interval of 0 is given it will compare the current cpu times against the last call.
func Percent(interval time.Duration, percpu bool) ([]float64, error) {
if interval <= 0 {
return percentUsedFromLastCall(percpu)
}

// Get CPU usage at the start of the interval.
cpuTimes1, err := Times(percpu)
if err != nil {
return nil, err
}

time.Sleep(interval)

// And at the end of the interval.
cpuTimes2, err := Times(percpu)
if err != nil {
return nil, err
}

return calculateAllBusy(cpuTimes1, cpuTimes2)
}

func percentUsedFromLastCall(percpu bool) ([]float64, error) {
cpuTimes, err := Times(percpu)
if err != nil {
return nil, err
}
lastCPUPercent.Lock()
defer lastCPUPercent.Unlock()
var lastTimes []TimesStat
if percpu {
lastTimes = lastCPUPercent.lastPerCPUTimes
lastCPUPercent.lastPerCPUTimes = cpuTimes
} else {
lastTimes = lastCPUPercent.lastCPUTimes
lastCPUPercent.lastCPUTimes = cpuTimes
}

if lastTimes == nil {
return nil, fmt.Errorf("Error getting times for cpu percent. LastTimes was nil")
}
return calculateAllBusy(lastTimes, cpuTimes)
}
90 changes: 0 additions & 90 deletions cpu/cpu_unix.go

This file was deleted.

19 changes: 0 additions & 19 deletions cpu/cpu_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ package cpu
import (
"fmt"
"syscall"
"time"
"unsafe"

"github.com/StackExchange/wmi"
Expand Down Expand Up @@ -85,21 +84,3 @@ func Info() ([]InfoStat, error) {

return ret, nil
}

func Percent(interval time.Duration, percpu bool) ([]float64, error) {
var ret []float64
var dst []Win32_Processor
q := wmi.CreateQuery(&dst, "")
err := wmi.Query(q, &dst)
if err != nil {
return ret, err
}
for _, l := range dst {
// use range but windows can only get one percent.
if l.LoadPercentage == nil {
continue
}
ret = append(ret, float64(*l.LoadPercentage))
}
return ret, nil
}

0 comments on commit 832dcb9

Please sign in to comment.