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)