Enable bazel profiling in soong_build.

Bazel is executed several times during the execution of soong_build.
For each bazel execution, generate a profile and save under the
BAZEL_METRICS_DIR which is defined in soong_ui.

Bug: b/174479924
Test: * USE_BAZEL_ANALYSIS=1 USE_BAZEL=1 m nothing and checked
        if the cquery and graph build bazel profiles were generated.
      * Verified that the generated bazel profiles were uploaded
        to the local dev metrics pipeline.

Change-Id: I3d20204484dc6c5a1525a5d3eec1d62cfb33535b
This commit is contained in:
Patrice Arruda 2020-12-12 06:24:26 +00:00
parent 57fab96e01
commit 05ab2d0731
7 changed files with 54 additions and 7 deletions

View file

@ -26,6 +26,8 @@ import (
"strings" "strings"
"sync" "sync"
"android/soong/bazel"
"android/soong/shared"
"github.com/google/blueprint/bootstrap" "github.com/google/blueprint/bootstrap"
) )
@ -68,6 +70,7 @@ type bazelContext struct {
outputBase string outputBase string
workspaceDir string workspaceDir string
buildDir string buildDir string
metricsDir string
requests map[cqueryKey]bool // cquery requests that have not yet been issued to Bazel requests map[cqueryKey]bool // cquery requests that have not yet been issued to Bazel
requestMutex sync.Mutex // requests can be written in parallel requestMutex sync.Mutex // requests can be written in parallel
@ -153,6 +156,11 @@ func NewBazelContext(c *config) (BazelContext, error) {
} else { } else {
missingEnvVars = append(missingEnvVars, "BAZEL_WORKSPACE") missingEnvVars = append(missingEnvVars, "BAZEL_WORKSPACE")
} }
if len(c.Getenv("BAZEL_METRICS_DIR")) > 1 {
bazelCtx.metricsDir = c.Getenv("BAZEL_METRICS_DIR")
} else {
missingEnvVars = append(missingEnvVars, "BAZEL_METRICS_DIR")
}
if len(missingEnvVars) > 0 { if len(missingEnvVars) > 0 {
return nil, errors.New(fmt.Sprintf("missing required env vars to use bazel: %s", missingEnvVars)) return nil, errors.New(fmt.Sprintf("missing required env vars to use bazel: %s", missingEnvVars))
} else { } else {
@ -160,6 +168,10 @@ func NewBazelContext(c *config) (BazelContext, error) {
} }
} }
func (context *bazelContext) BazelMetricsDir() string {
return context.metricsDir
}
func (context *bazelContext) BazelEnabled() bool { func (context *bazelContext) BazelEnabled() bool {
return true return true
} }
@ -189,12 +201,13 @@ func pwdPrefix() string {
return "" return ""
} }
func (context *bazelContext) issueBazelCommand(command string, labels []string, func (context *bazelContext) issueBazelCommand(runName bazel.RunName, command string, labels []string,
extraFlags ...string) (string, error) { extraFlags ...string) (string, error) {
cmdFlags := []string{"--output_base=" + context.outputBase, command} cmdFlags := []string{"--output_base=" + context.outputBase, command}
cmdFlags = append(cmdFlags, labels...) cmdFlags = append(cmdFlags, labels...)
cmdFlags = append(cmdFlags, "--package_path=%workspace%/"+context.intermediatesDir()) cmdFlags = append(cmdFlags, "--package_path=%workspace%/"+context.intermediatesDir())
cmdFlags = append(cmdFlags, "--profile="+shared.BazelMetricsFilename(context, runName))
cmdFlags = append(cmdFlags, extraFlags...) cmdFlags = append(cmdFlags, extraFlags...)
bazelCmd := exec.Command(context.bazelPath, cmdFlags...) bazelCmd := exec.Command(context.bazelPath, cmdFlags...)
@ -341,7 +354,7 @@ func (context *bazelContext) InvokeBazel() error {
return err return err
} }
buildroot_label := "//:buildroot" buildroot_label := "//:buildroot"
cqueryOutput, err = context.issueBazelCommand("cquery", cqueryOutput, err = context.issueBazelCommand(bazel.CqueryBuildRootRunName, "cquery",
[]string{fmt.Sprintf("deps(%s)", buildroot_label)}, []string{fmt.Sprintf("deps(%s)", buildroot_label)},
"--output=starlark", "--output=starlark",
"--starlark:file="+cquery_file_relpath) "--starlark:file="+cquery_file_relpath)
@ -371,7 +384,7 @@ func (context *bazelContext) InvokeBazel() error {
// bazel actions should either be added to the Ninja file and executed later, // bazel actions should either be added to the Ninja file and executed later,
// or bazel should handle execution. // or bazel should handle execution.
// TODO(cparsons): Use --target_pattern_file to avoid command line limits. // TODO(cparsons): Use --target_pattern_file to avoid command line limits.
_, err = context.issueBazelCommand("build", []string{buildroot_label}) _, err = context.issueBazelCommand(bazel.BazelBuildPhonyRootRunName, "build", []string{buildroot_label})
if err != nil { if err != nil {
return err return err

View file

@ -2,6 +2,7 @@ bootstrap_go_package {
name: "soong-bazel", name: "soong-bazel",
pkgPath: "android/soong/bazel", pkgPath: "android/soong/bazel",
srcs: [ srcs: [
"constants.go",
"properties.go", "properties.go",
], ],
pluginFor: [ pluginFor: [

26
bazel/constants.go Normal file
View file

@ -0,0 +1,26 @@
package bazel
type RunName string
// Below is a list bazel execution run names used through out the
// Platform Build systems. Each run name represents an unique key
// to query the bazel metrics.
const (
// Perform a bazel build of the phony root to generate symlink forests
// for dependencies of the bazel build.
BazelBuildPhonyRootRunName = RunName("bazel-build-phony-root")
// Perform aquery of the bazel build root to retrieve action information.
AqueryBuildRootRunName = RunName("aquery-buildroot")
// Perform cquery of the Bazel build root and its dependencies.
CqueryBuildRootRunName = RunName("cquery-buildroot")
// Run bazel as a ninja executer
BazelNinjaExecRunName = RunName("bazel-ninja-exec")
)
// String returns the name of the run.
func (c RunName) String() string {
return string(c)
}

View file

@ -4,4 +4,7 @@ bootstrap_go_package {
srcs: [ srcs: [
"paths.go", "paths.go",
], ],
deps: [
"soong-bazel",
],
} }

View file

@ -18,6 +18,8 @@ package shared
import ( import (
"path/filepath" "path/filepath"
"android/soong/bazel"
) )
// A SharedPaths represents a list of paths that are shared between // A SharedPaths represents a list of paths that are shared between
@ -37,6 +39,6 @@ func TempDirForOutDir(outDir string) (tempPath string) {
// on the action name. This is to help to store a set of bazel // on the action name. This is to help to store a set of bazel
// profiles since bazel may execute multiple times during a single // profiles since bazel may execute multiple times during a single
// build. // build.
func BazelMetricsFilename(s SharedPaths, actionName string) string { func BazelMetricsFilename(s SharedPaths, actionName bazel.RunName) string {
return filepath.Join(s.BazelMetricsDir(), actionName+"_bazel_profile.gz") return filepath.Join(s.BazelMetricsDir(), actionName.String()+"_bazel_profile.gz")
} }

View file

@ -22,6 +22,7 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"android/soong/bazel"
"android/soong/shared" "android/soong/shared"
"android/soong/ui/metrics" "android/soong/ui/metrics"
) )
@ -97,9 +98,9 @@ func runBazel(ctx Context, config Config) {
} }
// Start constructing the `build` command. // Start constructing the `build` command.
actionName := "build" actionName := bazel.BazelNinjaExecRunName
cmd.Args = append(cmd.Args, cmd.Args = append(cmd.Args,
actionName, "build",
// Use output_groups to select the set of outputs to produce from a // Use output_groups to select the set of outputs to produce from a
// ninja_build target. // ninja_build target.
"--output_groups="+outputGroups, "--output_groups="+outputGroups,

View file

@ -156,6 +156,7 @@ func runSoong(ctx Context, config Config) {
cmd.Environment.Set("BAZEL_HOME", filepath.Join(config.BazelOutDir(), "bazelhome")) cmd.Environment.Set("BAZEL_HOME", filepath.Join(config.BazelOutDir(), "bazelhome"))
cmd.Environment.Set("BAZEL_OUTPUT_BASE", filepath.Join(config.BazelOutDir(), "output")) cmd.Environment.Set("BAZEL_OUTPUT_BASE", filepath.Join(config.BazelOutDir(), "output"))
cmd.Environment.Set("BAZEL_WORKSPACE", absPath(ctx, ".")) cmd.Environment.Set("BAZEL_WORKSPACE", absPath(ctx, "."))
cmd.Environment.Set("BAZEL_METRICS_DIR", config.BazelMetricsDir())
cmd.Environment.Set("SOONG_SANDBOX_SOONG_BUILD", "true") cmd.Environment.Set("SOONG_SANDBOX_SOONG_BUILD", "true")
cmd.Sandbox = soongSandbox cmd.Sandbox = soongSandbox