Skip to content

Commit 58cc312

Browse files
hodgesdsoblitorum
authored andcommitted
Fix initialization in perf collector when using multiple CPUs (prometheus#1665)
* Fix initialization in perf collector when using multiple CPUs Signed-off-by: Daniel Hodges <hodges.daniel.scott@gmail.com>
1 parent 1defa36 commit 58cc312

File tree

2 files changed

+66
-2
lines changed

2 files changed

+66
-2
lines changed

collector/perf_linux.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,18 +135,21 @@ func NewPerfCollector(logger log.Logger) (Collector, error) {
135135
return nil, err
136136
}
137137
collector.perfHwProfilers[cpu] = &hwProf
138+
collector.hwProfilerCPUMap[&hwProf] = cpu
138139

139140
swProf := perf.NewSoftwareProfiler(-1, cpu)
140141
if err := swProf.Start(); err != nil {
141142
return nil, err
142143
}
143144
collector.perfSwProfilers[cpu] = &swProf
145+
collector.swProfilerCPUMap[&swProf] = cpu
144146

145147
cacheProf := perf.NewCacheProfiler(-1, cpu)
146148
if err := cacheProf.Start(); err != nil {
147149
return nil, err
148150
}
149151
collector.perfCacheProfilers[cpu] = &cacheProf
152+
collector.cacheProfilerCPUMap[&cacheProf] = cpu
150153
}
151154

152155
collector.desc = map[string]*prometheus.Desc{

collector/perf_linux_test.go

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,18 @@
1616
package collector
1717

1818
import (
19-
"github.com/go-kit/kit/log"
2019
"io/ioutil"
20+
"runtime"
2121
"strconv"
2222
"strings"
2323
"testing"
2424

25+
"github.com/go-kit/kit/log"
26+
2527
"github.com/prometheus/client_golang/prometheus"
2628
)
2729

28-
func TestPerfCollector(t *testing.T) {
30+
func canTestPerf(t *testing.T) {
2931
paranoidBytes, err := ioutil.ReadFile("/proc/sys/kernel/perf_event_paranoid")
3032
if err != nil {
3133
t.Skip("Procfs not mounted, skipping perf tests")
@@ -38,6 +40,10 @@ func TestPerfCollector(t *testing.T) {
3840
if paranoid >= 1 {
3941
t.Skip("Skipping perf tests, set perf_event_paranoid to 0")
4042
}
43+
}
44+
45+
func TestPerfCollector(t *testing.T) {
46+
canTestPerf(t)
4147
collector, err := NewPerfCollector(log.NewNopLogger())
4248
if err != nil {
4349
t.Fatal(err)
@@ -55,6 +61,61 @@ func TestPerfCollector(t *testing.T) {
5561
}
5662
}
5763

64+
func TestPerfCollectorStride(t *testing.T) {
65+
canTestPerf(t)
66+
67+
tests := []struct {
68+
name string
69+
flag string
70+
exCpus []int
71+
}{
72+
{
73+
name: "valid single cpu",
74+
flag: "1",
75+
exCpus: []int{1},
76+
},
77+
{
78+
name: "valid range cpus",
79+
flag: "1-5",
80+
exCpus: []int{1, 2, 3, 4, 5},
81+
},
82+
{
83+
name: "valid stride",
84+
flag: "1-8:2",
85+
exCpus: []int{1, 3, 5, 7},
86+
},
87+
}
88+
89+
for _, test := range tests {
90+
t.Run(test.name, func(t *testing.T) {
91+
ncpu := runtime.NumCPU()
92+
for _, cpu := range test.exCpus {
93+
if cpu > ncpu {
94+
t.Skipf("Skipping test because runtime.NumCPU < %d", cpu)
95+
}
96+
}
97+
perfCPUsFlag = &test.flag
98+
collector, err := NewPerfCollector(log.NewNopLogger())
99+
if err != nil {
100+
t.Fatal(err)
101+
}
102+
103+
c := collector.(*perfCollector)
104+
for _, cpu := range test.exCpus {
105+
if _, ok := c.perfHwProfilers[cpu]; !ok {
106+
t.Fatalf("Expected CPU %v in hardware profilers", cpu)
107+
}
108+
if _, ok := c.perfSwProfilers[cpu]; !ok {
109+
t.Fatalf("Expected CPU %v in software profilers", cpu)
110+
}
111+
if _, ok := c.perfCacheProfilers[cpu]; !ok {
112+
t.Fatalf("Expected CPU %v in cache profilers", cpu)
113+
}
114+
}
115+
})
116+
}
117+
}
118+
58119
func TestPerfCPUFlagToCPUs(t *testing.T) {
59120
tests := []struct {
60121
name string

0 commit comments

Comments
 (0)