Skip to content

Commit

Permalink
Collect both cpuinfo and scaling files (#123)
Browse files Browse the repository at this point in the history
Collect cpufreq `cpuinfo` and `scaling` files. They have different
meanings.
* Ignore not found and unreadable files.
* Return pointers for uint64 values.

Signed-off-by: Ben Kochie <superq@gmail.com>
  • Loading branch information
SuperQ authored Jan 4, 2019
1 parent 14fa759 commit b1a0a9a
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 56 deletions.
72 changes: 38 additions & 34 deletions sysfs/system_cpu.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
package sysfs

import (
"fmt"
"os"
"path/filepath"
"strings"
Expand All @@ -26,16 +25,19 @@ import (

// SystemCPUCpufreqStats contains stats from devices/system/cpu/cpu[0-9]*/cpufreq/...
type SystemCPUCpufreqStats struct {
Name string
CurrentFrequency uint64
MinimumFrequency uint64
MaximumFrequency uint64
TransitionLatency uint64
AvailableGovernors string
Driver string
Govenor string
RelatedCpus string
SetSpeed string
Name string
CpuinfoCurrentFrequency *uint64
CpuinfoMinimumFrequency *uint64
CpuinfoMaximumFrequency *uint64
CpuinfoTransitionLatency *uint64
ScalingCurrentFrequency *uint64
ScalingMinimumFrequency *uint64
ScalingMaximumFrequency *uint64
AvailableGovernors string
Driver string
Govenor string
RelatedCpus string
SetSpeed string
}

// TODO: Add topology support.
Expand Down Expand Up @@ -74,14 +76,7 @@ func (fs FS) NewSystemCpufreq() ([]SystemCPUCpufreqStats, error) {
return []SystemCPUCpufreqStats{}, err
}

if _, err = os.Stat(filepath.Join(cpuCpufreqPath, "scaling_cur_freq")); err == nil {
cpufreq, err = parseCpufreqCpuinfo("scaling", cpuCpufreqPath)
} else if _, err = os.Stat(filepath.Join(cpuCpufreqPath, "cpuinfo_cur_freq")); err == nil {
// Older kernels have metrics named `cpuinfo_...`.
cpufreq, err = parseCpufreqCpuinfo("cpuinfo", cpuCpufreqPath)
} else {
return []SystemCPUCpufreqStats{}, fmt.Errorf("CPU %v is missing cpufreq", cpu)
}
cpufreq, err = parseCpufreqCpuinfo(cpuCpufreqPath)
if err != nil {
return []SystemCPUCpufreqStats{}, err
}
Expand All @@ -92,22 +87,28 @@ func (fs FS) NewSystemCpufreq() ([]SystemCPUCpufreqStats, error) {
return systemCpufreq, nil
}

func parseCpufreqCpuinfo(prefix string, cpuPath string) (*SystemCPUCpufreqStats, error) {
func parseCpufreqCpuinfo(cpuPath string) (*SystemCPUCpufreqStats, error) {
uintFiles := []string{
prefix + "_cur_freq",
prefix + "_max_freq",
prefix + "_min_freq",
"cpuinfo_cur_freq",
"cpuinfo_max_freq",
"cpuinfo_min_freq",
"cpuinfo_transition_latency",
"scaling_cur_freq",
"scaling_max_freq",
"scaling_min_freq",
}
uintOut := make([]uint64, len(uintFiles))
uintOut := make([]*uint64, len(uintFiles))

for i, f := range uintFiles {
v, err := util.ReadUintFromFile(filepath.Join(cpuPath, f))
if err != nil {
if os.IsNotExist(err) || os.IsPermission(err) {
continue
}
return &SystemCPUCpufreqStats{}, err
}

uintOut[i] = v
uintOut[i] = &v
}

stringFiles := []string{
Expand All @@ -128,14 +129,17 @@ func parseCpufreqCpuinfo(prefix string, cpuPath string) (*SystemCPUCpufreqStats,
}

return &SystemCPUCpufreqStats{
CurrentFrequency: uintOut[0],
MaximumFrequency: uintOut[1],
MinimumFrequency: uintOut[2],
TransitionLatency: uintOut[3],
AvailableGovernors: stringOut[0],
Driver: stringOut[1],
Govenor: stringOut[2],
RelatedCpus: stringOut[3],
SetSpeed: stringOut[4],
CpuinfoCurrentFrequency: uintOut[0],
CpuinfoMaximumFrequency: uintOut[1],
CpuinfoMinimumFrequency: uintOut[2],
CpuinfoTransitionLatency: uintOut[3],
ScalingCurrentFrequency: uintOut[4],
ScalingMaximumFrequency: uintOut[5],
ScalingMinimumFrequency: uintOut[6],
AvailableGovernors: stringOut[0],
Driver: stringOut[1],
Govenor: stringOut[2],
RelatedCpus: stringOut[3],
SetSpeed: stringOut[4],
}, nil
}
54 changes: 32 additions & 22 deletions sysfs/system_cpu_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ import (
"testing"
)

func makeUint64(v uint64) *uint64 {
return &v
}

func TestNewSystemCpufreq(t *testing.T) {
fs, err := NewFS("fixtures")
if err != nil {
Expand All @@ -32,31 +36,37 @@ func TestNewSystemCpufreq(t *testing.T) {
}

systemCpufreq := []SystemCPUCpufreqStats{
// Ubuntu 16.04 (4.15.0-20-generic), has `scaling_cur_freq` file.
// Has missing `cpuinfo_cur_freq` file.
{
Name: "0",
CurrentFrequency: 1219917,
MinimumFrequency: 800000,
MaximumFrequency: 2400000,
TransitionLatency: 0,
AvailableGovernors: "performance powersave",
Driver: "intel_pstate",
Govenor: "powersave",
RelatedCpus: "0",
SetSpeed: "<unsupported>",
Name: "0",
CpuinfoCurrentFrequency: nil,
CpuinfoMinimumFrequency: makeUint64(800000),
CpuinfoMaximumFrequency: makeUint64(2400000),
CpuinfoTransitionLatency: makeUint64(0),
ScalingCurrentFrequency: makeUint64(1219917),
ScalingMinimumFrequency: makeUint64(800000),
ScalingMaximumFrequency: makeUint64(2400000),
AvailableGovernors: "performance powersave",
Driver: "intel_pstate",
Govenor: "powersave",
RelatedCpus: "0",
SetSpeed: "<unsupported>",
},
// RHEL 7.3 (3.10.0-514.26.2.el7), missing `scaling_cur_freq` file.
// Has missing `scaling_cur_freq` file.
{
Name: "1",
CurrentFrequency: 1200195,
MinimumFrequency: 1200000,
MaximumFrequency: 3300000,
TransitionLatency: 4294967295,
AvailableGovernors: "performance powersave",
Driver: "intel_pstate",
Govenor: "powersave",
RelatedCpus: "1",
SetSpeed: "<unsupported>",
Name: "1",
CpuinfoCurrentFrequency: makeUint64(1200195),
CpuinfoMinimumFrequency: makeUint64(1200000),
CpuinfoMaximumFrequency: makeUint64(3300000),
CpuinfoTransitionLatency: makeUint64(4294967295),
ScalingCurrentFrequency: nil,
ScalingMinimumFrequency: makeUint64(1200000),
ScalingMaximumFrequency: makeUint64(3300000),
AvailableGovernors: "performance powersave",
Driver: "intel_pstate",
Govenor: "powersave",
RelatedCpus: "1",
SetSpeed: "<unsupported>",
},
}

Expand Down

0 comments on commit b1a0a9a

Please sign in to comment.