process: implement cpu_percent on linux.

pull/43/merge
Shirou WAKAYAMA 10 years ago
parent e71113cffd
commit 2093d43c2a

@ -2,6 +2,10 @@ package process
import ( import (
"encoding/json" "encoding/json"
"runtime"
"time"
cpu "github.com/shirou/gopsutil/cpu"
) )
type Process struct { type Process struct {
@ -13,6 +17,9 @@ type Process struct {
gids []int32 gids []int32
numThreads int32 numThreads int32
memInfo *MemoryInfoStat memInfo *MemoryInfoStat
lastCPUTimes *cpu.CPUTimesStat
lastCPUTime time.Time
} }
type OpenFilesStat struct { type OpenFilesStat struct {
@ -88,3 +95,48 @@ func PidExists(pid int32) (bool, error) {
return false, err return false, err
} }
// If interval is 0, return difference from last call(non-blocking).
// If interval > 0, wait interval sec and return diffrence between start and end.
func (p *Process) CPUPercent(interval time.Duration) (float64, error) {
calculate := func(t1, t2 *cpu.CPUTimesStat, delta float64) float64 {
if delta == 0 {
return 0
}
numcpu := runtime.NumCPU()
delta_proc := (t2.User - t1.User) + (t2.System - t1.System)
overall_percent := ((delta_proc / delta) * 100) * float64(numcpu)
return overall_percent
}
cpuTimes, err := p.CPUTimes()
if err != nil {
return 0, err
}
if interval > 0 {
p.lastCPUTimes = cpuTimes
p.lastCPUTime = time.Now()
time.Sleep(interval)
cpuTimes, err = p.CPUTimes()
if err != nil {
return 0, err
}
} else {
if p.lastCPUTimes == nil {
// invoked first time
p.lastCPUTimes, err = p.CPUTimes()
if err != nil {
return 0, err
}
p.lastCPUTime = time.Now()
return 0, nil
}
}
delta := (time.Now().Sub(p.lastCPUTime).Seconds()) * 1000
ret := calculate(p.lastCPUTimes, cpuTimes, float64(delta))
p.lastCPUTimes = cpuTimes
p.lastCPUTime = time.Now()
return ret, nil
}

@ -148,9 +148,6 @@ func (p *Process) CPUTimes() (*cpu.CPUTimesStat, error) {
} }
return cpuTimes, nil return cpuTimes, nil
} }
func (p *Process) CPUPercent() (int32, error) {
return 0, common.NotImplementedError
}
func (p *Process) CPUAffinity() ([]int32, error) { func (p *Process) CPUAffinity() ([]int32, error) {
return nil, common.NotImplementedError return nil, common.NotImplementedError
} }
@ -545,6 +542,7 @@ func (p *Process) fillFromStat() (string, int32, *cpu.CPUTimesStat, int64, int32
if err != nil { if err != nil {
return "", 0, nil, 0, 0, err return "", 0, nil, 0, 0, err
} }
stime, err := strconv.ParseFloat(fields[14], 64) stime, err := strconv.ParseFloat(fields[14], 64)
if err != nil { if err != nil {
return "", 0, nil, 0, 0, err return "", 0, nil, 0, 0, err

@ -4,6 +4,7 @@ import (
"os" "os"
"runtime" "runtime"
"testing" "testing"
"time"
) )
func testGetProcess() Process { func testGetProcess() Process {
@ -126,3 +127,38 @@ func Test_Process_Nice(t *testing.T) {
return return
} }
} }
func Test_Process_CpuPercent(t *testing.T) {
p := testGetProcess()
percent, err := p.CPUPercent(0)
if err != nil {
t.Errorf("error %v", err)
}
duration := time.Duration(1000) * time.Microsecond
time.Sleep(duration)
percent, err = p.CPUPercent(0)
if err != nil {
t.Errorf("error %v", err)
}
numcpu := runtime.NumCPU()
if percent < 0.0 || percent > 100.0*float64(numcpu) {
t.Fatalf("CPUPercent value is invalid: %f", percent)
}
}
func Test_Process_CpuPercentLoop(t *testing.T) {
p := testGetProcess()
numcpu := runtime.NumCPU()
for i := 0; i < 2; i++ {
duration := time.Duration(100) * time.Microsecond
percent, err := p.CPUPercent(duration)
if err != nil {
t.Errorf("error %v", err)
}
if percent < 0.0 || percent > 100.0*float64(numcpu) {
t.Fatalf("CPUPercent value is invalid: %f", percent)
}
}
}

Loading…
Cancel
Save