Collect more metrics for aquery handling
Test: go test soong tests
Test: m nothing & verify metrics
Change-Id: Id19e004d90dfbaa1b1706c607d5250bf845c0f3b
diff --git a/bazel/aquery.go b/bazel/aquery.go
index 80cf70a..6a5e054 100644
--- a/bazel/aquery.go
+++ b/bazel/aquery.go
@@ -23,9 +23,11 @@
"sort"
"strings"
+ analysis_v2_proto "prebuilts/bazel/common/proto/analysis_v2"
+
+ "github.com/google/blueprint/metrics"
"github.com/google/blueprint/proptools"
"google.golang.org/protobuf/proto"
- analysis_v2_proto "prebuilts/bazel/common/proto/analysis_v2"
)
type artifactId int
@@ -313,7 +315,7 @@
// action graph, as described by the given action graph json proto.
// BuildStatements are one-to-one with actions in the given action graph, and AqueryDepsets
// are one-to-one with Bazel's depSetOfFiles objects.
-func AqueryBuildStatements(aqueryJsonProto []byte) ([]BuildStatement, []AqueryDepset, error) {
+func AqueryBuildStatements(aqueryJsonProto []byte, eventHandler *metrics.EventHandler) ([]BuildStatement, []AqueryDepset, error) {
aqueryProto := &analysis_v2_proto.ActionGraphContainer{}
err := proto.Unmarshal(aqueryJsonProto, aqueryProto)
if err != nil {
@@ -387,74 +389,92 @@
ParentId: pathFragmentId(protoPathFragments.ParentId)})
}
- aqueryHandler, err := newAqueryHandler(aqueryResult)
- if err != nil {
- return nil, nil, err
- }
- var buildStatements []BuildStatement
- for _, actionEntry := range aqueryResult.Actions {
- if shouldSkipAction(actionEntry) {
- continue
- }
-
- var buildStatement BuildStatement
- if actionEntry.isSymlinkAction() {
- buildStatement, err = aqueryHandler.symlinkActionBuildStatement(actionEntry)
- } else if actionEntry.isTemplateExpandAction() && len(actionEntry.Arguments) < 1 {
- buildStatement, err = aqueryHandler.templateExpandActionBuildStatement(actionEntry)
- } else if actionEntry.isFileWriteAction() {
- buildStatement, err = aqueryHandler.fileWriteActionBuildStatement(actionEntry)
- } else if actionEntry.isSymlinkTreeAction() {
- buildStatement, err = aqueryHandler.symlinkTreeActionBuildStatement(actionEntry)
- } else if len(actionEntry.Arguments) < 1 {
- return nil, nil, fmt.Errorf("received action with no command: [%s]", actionEntry.Mnemonic)
- } else {
- buildStatement, err = aqueryHandler.normalActionBuildStatement(actionEntry)
- }
-
+ var aqueryHandler *aqueryArtifactHandler
+ {
+ eventHandler.Begin("init_handler")
+ defer eventHandler.End("init_handler")
+ aqueryHandler, err = newAqueryHandler(aqueryResult)
if err != nil {
return nil, nil, err
}
- buildStatements = append(buildStatements, buildStatement)
+ }
+
+ var buildStatements []BuildStatement
+ {
+ eventHandler.Begin("build_statements")
+ defer eventHandler.End("build_statements")
+ for _, actionEntry := range aqueryResult.Actions {
+ if shouldSkipAction(actionEntry) {
+ continue
+ }
+
+ var buildStatement BuildStatement
+ if actionEntry.isSymlinkAction() {
+ buildStatement, err = aqueryHandler.symlinkActionBuildStatement(actionEntry)
+ } else if actionEntry.isTemplateExpandAction() && len(actionEntry.Arguments) < 1 {
+ buildStatement, err = aqueryHandler.templateExpandActionBuildStatement(actionEntry)
+ } else if actionEntry.isFileWriteAction() {
+ buildStatement, err = aqueryHandler.fileWriteActionBuildStatement(actionEntry)
+ } else if actionEntry.isSymlinkTreeAction() {
+ buildStatement, err = aqueryHandler.symlinkTreeActionBuildStatement(actionEntry)
+ } else if len(actionEntry.Arguments) < 1 {
+ err = fmt.Errorf("received action with no command: [%s]", actionEntry.Mnemonic)
+ } else {
+ buildStatement, err = aqueryHandler.normalActionBuildStatement(actionEntry)
+ }
+
+ if err != nil {
+ return nil, nil, err
+ }
+ buildStatements = append(buildStatements, buildStatement)
+ }
}
depsetsByHash := map[string]AqueryDepset{}
var depsets []AqueryDepset
- for _, aqueryDepset := range aqueryHandler.depsetIdToAqueryDepset {
- if prevEntry, hasKey := depsetsByHash[aqueryDepset.ContentHash]; hasKey {
- // Two depsets collide on hash. Ensure that their contents are identical.
- if !reflect.DeepEqual(aqueryDepset, prevEntry) {
- return nil, nil, fmt.Errorf("two different depsets have the same hash: %v, %v", prevEntry, aqueryDepset)
+ {
+ eventHandler.Begin("depsets")
+ defer eventHandler.End("depsets")
+ for _, aqueryDepset := range aqueryHandler.depsetIdToAqueryDepset {
+ if prevEntry, hasKey := depsetsByHash[aqueryDepset.ContentHash]; hasKey {
+ // Two depsets collide on hash. Ensure that their contents are identical.
+ if !reflect.DeepEqual(aqueryDepset, prevEntry) {
+ return nil, nil, fmt.Errorf("two different depsets have the same hash: %v, %v", prevEntry, aqueryDepset)
+ }
+ } else {
+ depsetsByHash[aqueryDepset.ContentHash] = aqueryDepset
+ depsets = append(depsets, aqueryDepset)
}
- } else {
- depsetsByHash[aqueryDepset.ContentHash] = aqueryDepset
- depsets = append(depsets, aqueryDepset)
}
}
- // Build Statements and depsets must be sorted by their content hash to
- // preserve determinism between builds (this will result in consistent ninja file
- // output). Note they are not sorted by their original IDs nor their Bazel ordering,
- // as Bazel gives nondeterministic ordering / identifiers in aquery responses.
- sort.Slice(buildStatements, func(i, j int) bool {
- // For build statements, compare output lists. In Bazel, each output file
- // may only have one action which generates it, so this will provide
- // a deterministic ordering.
- outputs_i := buildStatements[i].OutputPaths
- outputs_j := buildStatements[j].OutputPaths
- if len(outputs_i) != len(outputs_j) {
- return len(outputs_i) < len(outputs_j)
- }
- if len(outputs_i) == 0 {
- // No outputs for these actions, so compare commands.
- return buildStatements[i].Command < buildStatements[j].Command
- }
- // There may be multiple outputs, but the output ordering is deterministic.
- return outputs_i[0] < outputs_j[0]
+ eventHandler.Do("build_statement_sort", func() {
+ // Build Statements and depsets must be sorted by their content hash to
+ // preserve determinism between builds (this will result in consistent ninja file
+ // output). Note they are not sorted by their original IDs nor their Bazel ordering,
+ // as Bazel gives nondeterministic ordering / identifiers in aquery responses.
+ sort.Slice(buildStatements, func(i, j int) bool {
+ // For build statements, compare output lists. In Bazel, each output file
+ // may only have one action which generates it, so this will provide
+ // a deterministic ordering.
+ outputs_i := buildStatements[i].OutputPaths
+ outputs_j := buildStatements[j].OutputPaths
+ if len(outputs_i) != len(outputs_j) {
+ return len(outputs_i) < len(outputs_j)
+ }
+ if len(outputs_i) == 0 {
+ // No outputs for these actions, so compare commands.
+ return buildStatements[i].Command < buildStatements[j].Command
+ }
+ // There may be multiple outputs, but the output ordering is deterministic.
+ return outputs_i[0] < outputs_j[0]
+ })
})
- sort.Slice(depsets, func(i, j int) bool {
- return depsets[i].ContentHash < depsets[j].ContentHash
+ eventHandler.Do("depset_sort", func() {
+ sort.Slice(depsets, func(i, j int) bool {
+ return depsets[i].ContentHash < depsets[j].ContentHash
+ })
})
return buildStatements, depsets, nil
}