mirror of
https://github.com/shirou/gopsutil.git
synced 2025-04-29 13:49:21 +08:00
calculate cpu percentage compared to last call if 0 interval is given
This commit is contained in:
parent
bae75faa5a
commit
c389989453
18
cpu/cpu.go
18
cpu/cpu.go
@ -5,6 +5,7 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TimesStat struct {
|
type TimesStat struct {
|
||||||
@ -37,8 +38,21 @@ type InfoStat struct {
|
|||||||
Flags []string `json:"flags"`
|
Flags []string `json:"flags"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var lastCPUTimes []TimesStat
|
//CPUPercent
|
||||||
var lastPerCPUTimes []TimesStat
|
type cpuPercent struct {
|
||||||
|
sync.Mutex
|
||||||
|
lastCPUTimes []TimesStat
|
||||||
|
lastPerCPUTimes []TimesStat
|
||||||
|
}
|
||||||
|
|
||||||
|
var lastCPUPercent cpuPercent
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
lastCPUPercent.Lock()
|
||||||
|
lastCPUPercent.lastCPUTimes, _ = Times(false)
|
||||||
|
lastCPUPercent.lastPerCPUTimes, _ = Times(true)
|
||||||
|
lastCPUPercent.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
func Counts(logical bool) (int, error) {
|
func Counts(logical bool) (int, error) {
|
||||||
return runtime.NumCPU(), nil
|
return runtime.NumCPU(), nil
|
||||||
|
@ -94,6 +94,40 @@ func testCPUPercent(t *testing.T, percpu bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testCPUPercentLastUsed(t *testing.T, percpu bool) {
|
||||||
|
|
||||||
|
numcpu := runtime.NumCPU()
|
||||||
|
testCount := 10
|
||||||
|
|
||||||
|
if runtime.GOOS != "windows" {
|
||||||
|
testCount = 2
|
||||||
|
v, err := Percent(time.Millisecond, percpu)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error %v", err)
|
||||||
|
}
|
||||||
|
// Skip CircleCI which CPU num is different
|
||||||
|
if os.Getenv("CIRCLECI") != "true" {
|
||||||
|
if (percpu && len(v) != numcpu) || (!percpu && len(v) != 1) {
|
||||||
|
t.Fatalf("wrong number of entries from CPUPercent: %v", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i := 0; i < testCount; i++ {
|
||||||
|
v, err := Percent(0, percpu)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error %v", err)
|
||||||
|
}
|
||||||
|
time.Sleep(1 * time.Millisecond)
|
||||||
|
for _, percent := range v {
|
||||||
|
// Check for slightly greater then 100% to account for any rounding issues.
|
||||||
|
if percent < 0.0 || percent > 100.0001*float64(numcpu) {
|
||||||
|
t.Fatalf("CPUPercent value is invalid: %f", percent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func TestCPUPercent(t *testing.T) {
|
func TestCPUPercent(t *testing.T) {
|
||||||
testCPUPercent(t, false)
|
testCPUPercent(t, false)
|
||||||
}
|
}
|
||||||
@ -101,3 +135,11 @@ func TestCPUPercent(t *testing.T) {
|
|||||||
func TestCPUPercentPerCpu(t *testing.T) {
|
func TestCPUPercentPerCpu(t *testing.T) {
|
||||||
testCPUPercent(t, true)
|
testCPUPercent(t, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCPUPercentIntervalZero(t *testing.T) {
|
||||||
|
testCPUPercentLastUsed(t, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCPUPercentIntervalZeroPerCPU(t *testing.T) {
|
||||||
|
testCPUPercentLastUsed(t, true)
|
||||||
|
}
|
||||||
|
@ -7,14 +7,13 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Percent(interval time.Duration, percpu bool) ([]float64, error) {
|
func getAllBusy(t TimesStat) (float64, float64) {
|
||||||
getAllBusy := func(t TimesStat) (float64, float64) {
|
|
||||||
busy := t.User + t.System + t.Nice + t.Iowait + t.Irq +
|
busy := t.User + t.System + t.Nice + t.Iowait + t.Irq +
|
||||||
t.Softirq + t.Steal + t.Guest + t.GuestNice + t.Stolen
|
t.Softirq + t.Steal + t.Guest + t.GuestNice + t.Stolen
|
||||||
return busy + t.Idle, busy
|
return busy + t.Idle, busy
|
||||||
}
|
}
|
||||||
|
|
||||||
calculate := func(t1, t2 TimesStat) float64 {
|
func calculateBusy(t1, t2 TimesStat) float64 {
|
||||||
t1All, t1Busy := getAllBusy(t1)
|
t1All, t1Busy := getAllBusy(t1)
|
||||||
t2All, t2Busy := getAllBusy(t2)
|
t2All, t2Busy := getAllBusy(t2)
|
||||||
|
|
||||||
@ -27,15 +26,36 @@ func Percent(interval time.Duration, percpu bool) ([]float64, error) {
|
|||||||
return (t2Busy - t1Busy) / (t2All - t1All) * 100
|
return (t2Busy - t1Busy) / (t2All - t1All) * 100
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func calcualteALLBusy(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.
|
// Get CPU usage at the start of the interval.
|
||||||
cpuTimes1, err := Times(percpu)
|
cpuTimes1, err := Times(percpu)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if interval > 0 {
|
|
||||||
time.Sleep(interval)
|
time.Sleep(interval)
|
||||||
}
|
|
||||||
|
|
||||||
// And at the end of the interval.
|
// And at the end of the interval.
|
||||||
cpuTimes2, err := Times(percpu)
|
cpuTimes2, err := Times(percpu)
|
||||||
@ -43,17 +63,28 @@ func Percent(interval time.Duration, percpu bool) ([]float64, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the CPU measurements have the same length.
|
return calcualteALLBusy(cpuTimes1, cpuTimes2)
|
||||||
if len(cpuTimes1) != len(cpuTimes2) {
|
|
||||||
return nil, fmt.Errorf(
|
|
||||||
"received two CPU counts: %d != %d",
|
|
||||||
len(cpuTimes1), len(cpuTimes2),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret := make([]float64, len(cpuTimes1))
|
func percentUsedFromLastCall(percpu bool) ([]float64, error) {
|
||||||
for i, t := range cpuTimes2 {
|
cpuTimes, err := Times(percpu)
|
||||||
ret[i] = calculate(cpuTimes1[i], t)
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
return ret, nil
|
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 calcualteALLBusy(lastTimes, cpuTimes)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user