diff --git a/perf/collector_libpfm.go b/perf/collector_libpfm.go index 01ae2943184..889547a13ea 100644 --- a/perf/collector_libpfm.go +++ b/perf/collector_libpfm.go @@ -112,12 +112,17 @@ func readPerfStat(file readerCloser, name string, cpu int) (*info.PerfStat, erro } scalingRatio := 1.0 - if perfData.TimeEnabled != 0 { + if perfData.TimeRunning != 0 && perfData.TimeEnabled != 0 { scalingRatio = float64(perfData.TimeRunning) / float64(perfData.TimeEnabled) } + value := perfData.Value + if scalingRatio != float64(0) { + value = uint64(float64(value) / scalingRatio) + } + stat := info.PerfStat{ - Value: uint64(float64(perfData.Value) / scalingRatio), + Value: value, Name: name, ScalingRatio: scalingRatio, Cpu: cpu, diff --git a/perf/collector_libpfm_test.go b/perf/collector_libpfm_test.go index 8cc4632f031..39cf911372e 100644 --- a/perf/collector_libpfm_test.go +++ b/perf/collector_libpfm_test.go @@ -112,3 +112,135 @@ func TestNewCollector(t *testing.T) { assert.Nil(t, perfCollector.eventToCustomEvent[Event("event_1")]) assert.Same(t, &perfCollector.events.Core.CustomEvents[0], perfCollector.eventToCustomEvent[Event("event_2")]) } + + +var readPerfStatCases = []struct { + test string + file ReadFormat + name string + cpu int + perfStat info.PerfStat + err error +}{ + { + test: "no scaling", + file: ReadFormat{ + Value: 5, + TimeEnabled: 0, + TimeRunning: 0, + ID: 0, + }, + name: "some metric", + cpu: 1, + perfStat: info.PerfStat{ + ScalingRatio: 1, + Value: 5, + Name: "some metric", + Cpu: 1, + }, + err: nil, + }, + { + test: "no scaling - TimeEnabled = 0", + file: ReadFormat{ + Value: 5, + TimeEnabled: 0, + TimeRunning: 1, + ID: 0, + }, + name: "some metric", + cpu: 1, + perfStat: info.PerfStat{ + ScalingRatio: 1, + Value: 5, + Name: "some metric", + Cpu: 1, + }, + err: nil, + }, + { + test: "scaling - 0.5", + file: ReadFormat{ + Value: 4, + TimeEnabled: 4, + TimeRunning: 2, + ID: 0, + }, + name: "some metric", + cpu: 2, + perfStat: info.PerfStat{ + ScalingRatio: 0.5, + Value: 8, + Name: "some metric", + Cpu: 2, + }, + err: nil, + }, + { + test: "scaling - 0 (TimeEnabled = 1, TimeRunning = 0)", + file: ReadFormat{ + Value: 4, + TimeEnabled: 1, + TimeRunning: 0, + ID: 0, + }, + name: "some metric", + cpu: 3, + perfStat: info.PerfStat{ + ScalingRatio: 1.0, + Value: 4, + Name: "some metric", + Cpu: 3, + }, + err: nil, + }, + { + test: "scaling - 0 (TimeEnabled = 0, TimeRunning = 1)", + file: ReadFormat{ + Value: 4, + TimeEnabled: 0, + TimeRunning: 1, + ID: 0, + }, + name: "some metric", + cpu: 3, + perfStat: info.PerfStat{ + ScalingRatio: 1.0, + Value: 4, + Name: "some metric", + Cpu: 3, + }, + err: nil, + }, + { + test: "zeros, zeros everywhere", + file: ReadFormat{ + Value: 0, + TimeEnabled: 0, + TimeRunning: 0, + ID: 0, + }, + name: "some metric", + cpu: 4, + perfStat: info.PerfStat{ + ScalingRatio: 1.0, + Value: 0, + Name: "some metric", + Cpu: 4, + }, + err: nil, + }, +} + +func TestReadPerfStat(t *testing.T) { + for _, test := range readPerfStatCases { + t.Run(test.test, func(tt *testing.T) { + buf := &buffer{bytes.NewBuffer([]byte{})} + err := binary.Write(buf, binary.LittleEndian, test.file) + assert.NoError(tt, err) + stat, err := readPerfStat(buf, test.name, test.cpu) + assert.Equal(tt, test.perfStat, *stat) + assert.Equal(tt, test.err, err) + }) + } +}