Skip to content

Commit 32dcdff

Browse files
committed
resources: store sys cpu usage per step
This can be used to convert step usage to relative units. Signed-off-by: Tonis Tiigi <[email protected]>
1 parent 6a2f92d commit 32dcdff

File tree

6 files changed

+75
-21
lines changed

6 files changed

+75
-21
lines changed

executor/resources/monitor.go

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212

1313
"github.com/moby/buildkit/executor/resources/types"
1414
"github.com/moby/buildkit/util/network"
15+
"github.com/prometheus/procfs"
1516
"github.com/sirupsen/logrus"
1617
)
1718

@@ -27,14 +28,16 @@ var initOnce sync.Once
2728
var isCgroupV2 bool
2829

2930
type cgroupRecord struct {
30-
once sync.Once
31-
ns string
32-
sampler *Sub[*types.Sample]
33-
samples []*types.Sample
34-
err error
35-
done chan struct{}
36-
monitor *Monitor
37-
netSampler NetworkSampler
31+
once sync.Once
32+
ns string
33+
sampler *Sub[*types.Sample]
34+
samples []*types.Sample
35+
err error
36+
done chan struct{}
37+
monitor *Monitor
38+
netSampler NetworkSampler
39+
startCPUStat *procfs.CPUStat
40+
sysCPUStat *types.SysCPUStat
3841
}
3942

4043
func (r *cgroupRecord) Wait() error {
@@ -44,6 +47,9 @@ func (r *cgroupRecord) Wait() error {
4447
}
4548

4649
func (r *cgroupRecord) Start() {
50+
if stat, err := r.monitor.proc.Stat(); err == nil {
51+
r.startCPUStat = &stat.CPUTotal
52+
}
4753
s := NewSampler(2*time.Second, r.sample)
4854
r.sampler = s.Record()
4955
}
@@ -73,6 +79,26 @@ func (r *cgroupRecord) close() {
7379
} else {
7480
r.samples = s
7581
}
82+
83+
if r.startCPUStat != nil {
84+
stat, err := r.monitor.proc.Stat()
85+
if err == nil {
86+
cpu := &types.SysCPUStat{
87+
User: stat.CPUTotal.User - r.startCPUStat.User,
88+
Nice: stat.CPUTotal.Nice - r.startCPUStat.Nice,
89+
System: stat.CPUTotal.System - r.startCPUStat.System,
90+
Idle: stat.CPUTotal.Idle - r.startCPUStat.Idle,
91+
Iowait: stat.CPUTotal.Iowait - r.startCPUStat.Iowait,
92+
IRQ: stat.CPUTotal.IRQ - r.startCPUStat.IRQ,
93+
SoftIRQ: stat.CPUTotal.SoftIRQ - r.startCPUStat.SoftIRQ,
94+
Steal: stat.CPUTotal.Steal - r.startCPUStat.Steal,
95+
Guest: stat.CPUTotal.Guest - r.startCPUStat.Guest,
96+
GuestNice: stat.CPUTotal.GuestNice - r.startCPUStat.GuestNice,
97+
}
98+
r.sysCPUStat = cpu
99+
}
100+
}
101+
76102
})
77103
}
78104

@@ -110,12 +136,15 @@ func (r *cgroupRecord) sample(tm time.Time) (*types.Sample, error) {
110136
return sample, nil
111137
}
112138

113-
func (r *cgroupRecord) Samples() ([]*types.Sample, error) {
139+
func (r *cgroupRecord) Samples() (*types.Samples, error) {
114140
<-r.done
115141
if r.err != nil {
116142
return nil, r.err
117143
}
118-
return r.samples, nil
144+
return &types.Samples{
145+
Samples: r.samples,
146+
SysCPUStat: r.sysCPUStat,
147+
}, nil
119148
}
120149

121150
type nopRecord struct {
@@ -125,7 +154,7 @@ func (r *nopRecord) Wait() error {
125154
return nil
126155
}
127156

128-
func (r *nopRecord) Samples() ([]*types.Sample, error) {
157+
func (r *nopRecord) Samples() (*types.Samples, error) {
129158
return nil, nil
130159
}
131160

@@ -140,6 +169,7 @@ type Monitor struct {
140169
mu sync.Mutex
141170
closed chan struct{}
142171
records map[string]*cgroupRecord
172+
proc procfs.FS
143173
}
144174

145175
type NetworkSampler interface {
@@ -194,9 +224,15 @@ func NewMonitor() (*Monitor, error) {
194224
}
195225
})
196226

227+
fs, err := procfs.NewDefaultFS()
228+
if err != nil {
229+
return nil, err
230+
}
231+
197232
return &Monitor{
198233
closed: make(chan struct{}),
199234
records: make(map[string]*cgroupRecord),
235+
proc: fs,
200236
}, nil
201237
}
202238

executor/resources/types/types.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,25 @@ type Recorder interface {
1111
Start()
1212
CloseAsync(func(context.Context) error) error
1313
Wait() error
14-
Samples() ([]*Sample, error)
14+
Samples() (*Samples, error)
15+
}
16+
17+
type SysCPUStat struct {
18+
User float64 `json:"user"`
19+
Nice float64 `json:"nice"`
20+
System float64 `json:"system"`
21+
Idle float64 `json:"idle"`
22+
Iowait float64 `json:"iowait"`
23+
IRQ float64 `json:"irq"`
24+
SoftIRQ float64 `json:"softirq"`
25+
Steal float64 `json:"steal"`
26+
Guest float64 `json:"guest"`
27+
GuestNice float64 `json:"guestNice"`
28+
}
29+
30+
type Samples struct {
31+
Samples []*Sample `json:"samples,omitempty"`
32+
SysCPUStat *SysCPUStat `json:"sysCPUStat,omitempty"`
1533
}
1634

1735
// Sample represents a wrapper for sampled data of cgroupv2 controllers

solver/llbsolver/ops/exec.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,7 @@ func (e *ExecOp) loadSecretEnv(ctx context.Context, g session.Group) ([]string,
456456
func (e *ExecOp) IsProvenanceProvider() {
457457
}
458458

459-
func (e *ExecOp) Samples() ([]*resourcestypes.Sample, error) {
459+
func (e *ExecOp) Samples() (*resourcestypes.Samples, error) {
460460
if e.rec == nil {
461461
return nil, nil
462462
}

solver/llbsolver/provenance.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ func captureProvenance(ctx context.Context, res solver.CachedResultWithProvenanc
361361
if err != nil {
362362
return err
363363
}
364-
if len(samples) > 0 {
364+
if samples != nil {
365365
c.AddSamples(op.Digest(), samples)
366366
}
367367
case *ops.BuildOp:

solver/llbsolver/provenance/buildconfig.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ type BuildConfig struct {
1212
}
1313

1414
type BuildStep struct {
15-
ID string `json:"id,omitempty"`
16-
Op interface{} `json:"op,omitempty"`
17-
Inputs []string `json:"inputs,omitempty"`
18-
ResourceUsage []*resourcestypes.Sample `json:"resourceUsage,omitempty"`
15+
ID string `json:"id,omitempty"`
16+
Op interface{} `json:"op,omitempty"`
17+
Inputs []string `json:"inputs,omitempty"`
18+
ResourceUsage *resourcestypes.Samples `json:"resourceUsage,omitempty"`
1919
}
2020

2121
type Source struct {

solver/llbsolver/provenance/capture.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ type Capture struct {
5959
SSH []SSH
6060
NetworkAccess bool
6161
IncompleteMaterials bool
62-
Samples map[digest.Digest][]*resourcestypes.Sample
62+
Samples map[digest.Digest]*resourcestypes.Samples
6363
}
6464

6565
func (c *Capture) Merge(c2 *Capture) error {
@@ -217,9 +217,9 @@ func (c *Capture) AddSSH(s SSH) {
217217
c.SSH = append(c.SSH, s)
218218
}
219219

220-
func (c *Capture) AddSamples(dgst digest.Digest, samples []*resourcestypes.Sample) {
220+
func (c *Capture) AddSamples(dgst digest.Digest, samples *resourcestypes.Samples) {
221221
if c.Samples == nil {
222-
c.Samples = map[digest.Digest][]*resourcestypes.Sample{}
222+
c.Samples = map[digest.Digest]*resourcestypes.Samples{}
223223
}
224224
c.Samples[dgst] = samples
225225
}

0 commit comments

Comments
 (0)