From 5da962fa40f1c9b54ed78f10ba32429b396e712b Mon Sep 17 00:00:00 2001 From: Phil Frost Date: Sat, 13 Jul 2019 09:17:59 -0700 Subject: [PATCH] Fix seconds reported by schedstat As explained further in the code comments, the previous implementation was based on incorrect documentation and reported values 10000000 times too large for the values in seconds. Furthermore the RunningSeconds() and WaitingSeconds() methods are removed, as it's not this library's job to interpret these values. Signed-off-by: Phil Frost --- schedstat.go | 42 ++++++++++++++++-------------------------- schedstat_test.go | 40 +++++++++++++++------------------------- 2 files changed, 31 insertions(+), 51 deletions(-) diff --git a/schedstat.go b/schedstat.go index 86396c0d9..98221e368 100644 --- a/schedstat.go +++ b/schedstat.go @@ -31,6 +31,12 @@ var ( // See // https://www.kernel.org/doc/Documentation/scheduler/sched-stats.txt // for a detailed description of what these numbers mean. +// +// Note the current kernel documentation claims some of the time units are in +// jiffies when they are actually in nanoseconds since 2.6.23 with the +// introduction of CFS. A fix to the documentation is pending. See +// https://lore.kernel.org/patchwork/project/lkml/list/?series=403473 + type Schedstat struct { CPUs []*SchedstatCPU } @@ -39,16 +45,16 @@ type Schedstat struct { type SchedstatCPU struct { CPUNum string - RunningJiffies uint64 - WaitingJiffies uint64 - RunTimeslices uint64 + RunningNanoseconds uint64 + WaitingNanoseconds uint64 + RunTimeslices uint64 } // ProcSchedstat contains the values from /proc//schedstat type ProcSchedstat struct { - RunningJiffies uint64 - WaitingJiffies uint64 - RunTimeslices uint64 + RunningNanoseconds uint64 + WaitingNanoseconds uint64 + RunTimeslices uint64 } func (fs FS) Schedstat() (*Schedstat, error) { @@ -67,12 +73,12 @@ func (fs FS) Schedstat() (*Schedstat, error) { cpu := &SchedstatCPU{} cpu.CPUNum = match[1] - cpu.RunningJiffies, err = strconv.ParseUint(match[8], 10, 64) + cpu.RunningNanoseconds, err = strconv.ParseUint(match[8], 10, 64) if err != nil { continue } - cpu.WaitingJiffies, err = strconv.ParseUint(match[9], 10, 64) + cpu.WaitingNanoseconds, err = strconv.ParseUint(match[9], 10, 64) if err != nil { continue } @@ -93,12 +99,12 @@ func parseProcSchedstat(contents string) (stats ProcSchedstat, err error) { match := procLineRE.FindStringSubmatch(contents) if match != nil { - stats.RunningJiffies, err = strconv.ParseUint(match[1], 10, 64) + stats.RunningNanoseconds, err = strconv.ParseUint(match[1], 10, 64) if err != nil { return } - stats.WaitingJiffies, err = strconv.ParseUint(match[2], 10, 64) + stats.WaitingNanoseconds, err = strconv.ParseUint(match[2], 10, 64) if err != nil { return } @@ -110,19 +116,3 @@ func parseProcSchedstat(contents string) (stats ProcSchedstat, err error) { err = errors.New("could not parse schedstat") return } - -func (stat *SchedstatCPU) RunningSeconds() float64 { - return float64(stat.RunningJiffies) / userHZ -} - -func (stat *SchedstatCPU) WaitingSeconds() float64 { - return float64(stat.WaitingJiffies) / userHZ -} - -func (stat *ProcSchedstat) RunningSeconds() float64 { - return float64(stat.RunningJiffies) / userHZ -} - -func (stat *ProcSchedstat) WaitingSeconds() float64 { - return float64(stat.WaitingJiffies) / userHZ -} diff --git a/schedstat_test.go b/schedstat_test.go index 42e43f1c2..c6bee611b 100644 --- a/schedstat_test.go +++ b/schedstat_test.go @@ -13,7 +13,9 @@ package procfs -import "testing" +import ( + "testing" +) func TestSchedstat(t *testing.T) { stats, err := getProcFixtures(t).Schedstat() @@ -36,18 +38,12 @@ func TestSchedstat(t *testing.T) { t.Error("could not find cpu0") } - if want, have := uint64(2045936778163039), cpu.RunningJiffies; want != have { - t.Errorf("want RunningJiffies %v, have %v", want, have) - } - if want, have := float64(2045936778163039)/userHZ, cpu.RunningSeconds(); want != have { - t.Errorf("want RunningSeconds() %v, have %v", want, have) + if want, have := uint64(2045936778163039), cpu.RunningNanoseconds; want != have { + t.Errorf("want RunningNanoseconds %v, have %v", want, have) } - if want, have := uint64(343796328169361), cpu.WaitingJiffies; want != have { - t.Errorf("want WaitingJiffies %v, have %v", want, have) - } - if want, have := float64(343796328169361)/userHZ, cpu.WaitingSeconds(); want != have { - t.Errorf("want WaitingSeconds() %v, have %v", want, have) + if want, have := uint64(343796328169361), cpu.WaitingNanoseconds; want != have { + t.Errorf("want WaitingNanoseconds %v, have %v", want, have) } if want, have := uint64(4767485306), cpu.RunTimeslices; want != have { @@ -66,18 +62,12 @@ func TestProcSchedstat(t *testing.T) { t.Fatal(err) } - if want, have := uint64(411605849), schedstat.RunningJiffies; want != have { - t.Errorf("want RunningJiffies %v, have %v", want, have) - } - if want, have := float64(411605849)/userHZ, schedstat.RunningSeconds(); want != have { - t.Errorf("want RunningSeconds() %v, have %v", want, have) + if want, have := uint64(411605849), schedstat.RunningNanoseconds; want != have { + t.Errorf("want RunningNanoseconds %v, have %v", want, have) } - if want, have := uint64(93680043), schedstat.WaitingJiffies; want != have { - t.Errorf("want WaitingJiffies %v, have %v", want, have) - } - if want, have := float64(93680043)/userHZ, schedstat.WaitingSeconds(); want != have { - t.Errorf("want WaitingSeconds() %v, have %v", want, have) + if want, have := uint64(93680043), schedstat.WaitingNanoseconds; want != have { + t.Errorf("want WaitingNanoseconds %v, have %v", want, have) } if want, have := uint64(79), schedstat.RunTimeslices; want != have { @@ -113,11 +103,11 @@ func TestProcSchedstatMultipleLines(t *testing.T) { if err != nil { t.Fatal(err) } - if want, have := uint64(123), schedstat.RunningJiffies; want != have { - t.Errorf("want RunningJiffies %v, have %v", want, have) + if want, have := uint64(123), schedstat.RunningNanoseconds; want != have { + t.Errorf("want RunningNanoseconds %v, have %v", want, have) } - if want, have := uint64(456), schedstat.WaitingJiffies; want != have { - t.Errorf("want WaitingJiffies %v, have %v", want, have) + if want, have := uint64(456), schedstat.WaitingNanoseconds; want != have { + t.Errorf("want WaitingNanoseconds %v, have %v", want, have) } if want, have := uint64(789), schedstat.RunTimeslices; want != have { t.Errorf("want RunTimeslices %v, have %v", want, have)