process: implement cpu_percent on linux.

This commit is contained in:
Shirou WAKAYAMA 2015-03-04 00:02:09 +09:00
parent e71113cffd
commit 2093d43c2a
3 changed files with 89 additions and 3 deletions

View File

@ -2,6 +2,10 @@ package process
import (
"encoding/json"
"runtime"
"time"
cpu "github.com/shirou/gopsutil/cpu"
)
type Process struct {
@ -13,6 +17,9 @@ type Process struct {
gids []int32
numThreads int32
memInfo *MemoryInfoStat
lastCPUTimes *cpu.CPUTimesStat
lastCPUTime time.Time
}
type OpenFilesStat struct {
@ -88,3 +95,48 @@ func PidExists(pid int32) (bool, error) {
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
}

View File

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

View File

@ -4,6 +4,7 @@ import (
"os"
"runtime"
"testing"
"time"
)
func testGetProcess() Process {
@ -126,3 +127,38 @@ func Test_Process_Nice(t *testing.T) {
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)
}
}
}