Add performance counter metrics to build.trace.gz

Start a background goroutine at the beginning of soong_build that
captures the CPU usage, heap size, and total system memory every
second.  Propagate the values through soong_build_metrics.pb back
to soong_ui, and then into build.trace.gz.

Test: m nothing, examine build.trace.gz
Change-Id: Iad99f8f1f088f4f7f7d5f76566a38c0c4f4d0daa
This commit is contained in:
Colin Cross
2023-10-27 14:56:12 -07:00
parent aa9a273b40
commit 46b0c75204
6 changed files with 655 additions and 209 deletions

View File

@@ -46,6 +46,8 @@ type Tracer interface {
End(thread Thread)
Complete(name string, thread Thread, begin, end uint64)
CountersAtTime(name string, thread Thread, time uint64, counters []Counter)
ImportMicrofactoryLog(filename string)
StatusTracer() status.StatusOutput
@@ -247,3 +249,48 @@ func (t *tracerImpl) Complete(name string, thread Thread, begin, end uint64) {
Tid: uint64(thread),
})
}
type Counter struct {
Name string
Value int64
}
type countersMarshaller []Counter
var _ json.Marshaler = countersMarshaller(nil)
func (counters countersMarshaller) MarshalJSON() ([]byte, error) {
// This produces similar output to a map[string]int64, but maintains the order of the slice.
buf := bytes.Buffer{}
buf.WriteRune('{')
for i, counter := range counters {
name, err := json.Marshal(counter.Name)
if err != nil {
return nil, err
}
buf.Write(name)
buf.WriteByte(':')
value, err := json.Marshal(counter.Value)
if err != nil {
return nil, err
}
buf.Write(value)
if i != len(counters)-1 {
buf.WriteRune(',')
}
}
buf.WriteRune('}')
return buf.Bytes(), nil
}
// CountersAtTime writes a Counter event at the given timestamp in nanoseconds.
func (t *tracerImpl) CountersAtTime(name string, thread Thread, time uint64, counters []Counter) {
t.writeEvent(&viewerEvent{
Name: name,
Phase: "C",
Time: time / 1000,
Pid: 0,
Tid: uint64(thread),
Arg: countersMarshaller(counters),
})
}