Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[cpu][windows] cpu.Times(true) should not return percent values #611

Merged
merged 4 commits into from
Dec 9, 2018
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions cpu/cpu_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,44 @@ func TestCpu_times(t *testing.T) {
t.Errorf("could not get CPU User: %v", vv)
}
}

// test sum of per cpu stats is within margin of error for cpu total stats
cpuTotal, err := Times(false)
if err != nil {
t.Errorf("error %v", err)
}
if len(cpuTotal) == 0 {
t.Error("could not get CPUs ", err)
}
perCPU, err := Times(true)
if err != nil {
t.Errorf("error %v", err)
}
if len(perCPU) == 0 {
t.Error("could not get CPUs ", err)
}
var perCPUUserTimeSum float64
var perCPUSystemTimeSum float64
var perCPUIdleTimeSum float64
for _, pc := range perCPU {
perCPUUserTimeSum += pc.User
perCPUSystemTimeSum += pc.System
perCPUIdleTimeSum += pc.Idle
}
margin := 2.0
if !isWithinMargin(perCPUUserTimeSum, cpuTotal[0].User, margin) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use assert.InEpsilon (or assert.InDelta) instead.

t.Errorf("perCPUUserTimeSum (%f) not within margin (%f) of cpuTotal (%f)", perCPUUserTimeSum, margin, cpuTotal[0].User)
}
if !isWithinMargin(perCPUSystemTimeSum, cpuTotal[0].System, margin) {
t.Errorf("perCPUSystemTimeSum (%f) not within margin (%f) of cpuTotal (%f)", perCPUSystemTimeSum, margin, cpuTotal[0].System)
}
if !isWithinMargin(perCPUIdleTimeSum, cpuTotal[0].Idle, margin) {
t.Errorf("perCPUIdleTimeSum (%f) not within margin (%f) of cpuTotal (%f)", perCPUIdleTimeSum, margin, cpuTotal[0].Idle)
}
}

func isWithinMargin(n, source, margin float64) bool {
return n >= source-margin && n <= source+margin
}

func TestCpu_counts(t *testing.T) {
Expand Down
21 changes: 12 additions & 9 deletions cpu/cpu_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ type Win32_Processor struct {
MaxClockSpeed uint32
}

// win32_PerfFormattedData_Counters_ProcessorInformation stores instance value of the perf counters
type win32_PerfFormattedData_Counters_ProcessorInformation struct {
type win32_PerfRawData_Counters_ProcessorInformation struct {
Name string
PercentDPCTime uint64
PercentIdleTime uint64
Expand All @@ -44,6 +43,10 @@ type Win32_PerfFormattedData_PerfOS_System struct {
ProcessorQueueLength uint32
}

const (
win32_TicksPerSecond = 10000000.0
)

// Times returns times stat per cpu and combined for all CPUs
func Times(percpu bool) ([]TimesStat, error) {
return TimesWithContext(context.Background(), percpu)
Expand Down Expand Up @@ -119,13 +122,13 @@ func InfoWithContext(ctx context.Context) ([]InfoStat, error) {

// PerfInfo returns the performance counter's instance value for ProcessorInformation.
// Name property is the key by which overall, per cpu and per core metric is known.
func perfInfoWithContext(ctx context.Context) ([]win32_PerfFormattedData_Counters_ProcessorInformation, error) {
var ret []win32_PerfFormattedData_Counters_ProcessorInformation
func perfInfoWithContext(ctx context.Context) ([]win32_PerfRawData_Counters_ProcessorInformation, error) {
var ret []win32_PerfRawData_Counters_ProcessorInformation

q := wmi.CreateQuery(&ret, "WHERE NOT Name LIKE '%_Total'")
err := common.WMIQueryWithContext(ctx, q, &ret)
if err != nil {
return []win32_PerfFormattedData_Counters_ProcessorInformation{}, err
return []win32_PerfRawData_Counters_ProcessorInformation{}, err
}

return ret, err
Expand Down Expand Up @@ -157,10 +160,10 @@ func perCPUTimesWithContext(ctx context.Context) ([]TimesStat, error) {
for _, v := range stats {
c := TimesStat{
CPU: v.Name,
User: float64(v.PercentUserTime),
System: float64(v.PercentPrivilegedTime),
Idle: float64(v.PercentIdleTime),
Irq: float64(v.PercentInterruptTime),
User: float64(v.PercentUserTime) / win32_TicksPerSecond,
System: float64(v.PercentPrivilegedTime) / win32_TicksPerSecond,
Idle: float64(v.PercentIdleTime) / win32_TicksPerSecond,
Irq: float64(v.PercentInterruptTime) / win32_TicksPerSecond,
}
ret = append(ret, c)
}
Expand Down