Improve profiling support for repository_ctx.execute

This change improves upon #11131.
 * The first eighty characters of the command line are included
   in the profile. This should make it easier to correlate execution
   times with repository_ctx.execute callsides.
 * The different phases of a remote execution request are highlighted
   in the profile just as they are for remote action execution. In
   particular this exposes information about cache hits and execution
   times.

Example Profile

![Screenshot from 2020-04-17 15-20-46](https://user-images.githubusercontent.com/1388179/79573506-0d643000-80bf-11ea-90aa-9cf22624048c.png)

Closes #11143.

PiperOrigin-RevId: 307395271
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java
index 705e09e..46d93d5 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java
@@ -101,6 +101,9 @@
           "rules_cc/cc/private/toolchain/unix_cc_configure.bzl",
           "bazel_tools/tools/cpp/unix_cc_configure.bzl");
 
+  /** Max. number of command line args added as a profiler description. */
+  private static final int MAX_PROFILE_ARGS_LEN = 80;
+
   private final Rule rule;
   private final PathPackageLocator packageLocator;
   private final Path outputDirectory;
@@ -444,10 +447,14 @@
       }
     }
 
-    try {
+    ImmutableList<String> arguments = argumentsBuilder.build();
+
+    try (SilentCloseable c =
+        Profiler.instance()
+            .profile(ProfilerTask.STARLARK_REPOSITORY_FN, profileArgsDesc("remote", arguments))) {
       ExecutionResult result =
           remoteExecutor.execute(
-              argumentsBuilder.build(),
+              arguments,
               inputsBuilder.build(),
               getExecProperties(),
               ImmutableMap.copyOf(environment),
@@ -487,6 +494,30 @@
     }
   }
 
+  /** Returns the command line arguments as a string for display in the profiler. */
+  private static String profileArgsDesc(String method, List<String> args) {
+    StringBuilder b = new StringBuilder();
+    b.append(method).append(":");
+
+    final String sep = " ";
+    for (String arg : args) {
+      int appendLen = sep.length() + arg.length();
+      int remainingLen = MAX_PROFILE_ARGS_LEN - b.length();
+
+      if (appendLen <= remainingLen) {
+        b.append(sep);
+        b.append(arg);
+      } else {
+        String shortenedArg = (sep + arg).substring(0, remainingLen);
+        b.append(shortenedArg);
+        b.append("...");
+        break;
+      }
+    }
+
+    return b.toString();
+  }
+
   @Override
   public SkylarkExecutionResult execute(
       Sequence<?> arguments, // <String> or <SkylarkPath> or <Label> expected
@@ -502,10 +533,7 @@
         Dict.cast(uncheckedEnvironment, String.class, String.class, "environment");
 
     if (canExecuteRemote()) {
-      try (SilentCloseable c =
-          Profiler.instance().profile(ProfilerTask.STARLARK_REPOSITORY_FN, "executeRemote")) {
-        return executeRemote(arguments, timeout, environment, quiet, workingDirectory);
-      }
+      return executeRemote(arguments, timeout, environment, quiet, workingDirectory);
     }
 
     // Execute on the local/host machine
@@ -549,13 +577,18 @@
       workingDirectoryPath = getPath("execute()", workingDirectory).getPath();
     }
     createDirectory(workingDirectoryPath);
-    return SkylarkExecutionResult.builder(osObject.getEnvironmentVariables())
-        .addArguments(args)
-        .setDirectory(workingDirectoryPath.getPathFile())
-        .addEnvironmentVariables(environment)
-        .setTimeout(timeoutMillis)
-        .setQuiet(quiet)
-        .execute();
+
+    try (SilentCloseable c =
+        Profiler.instance()
+            .profile(ProfilerTask.STARLARK_REPOSITORY_FN, profileArgsDesc("local", args))) {
+      return SkylarkExecutionResult.builder(osObject.getEnvironmentVariables())
+          .addArguments(args)
+          .setDirectory(workingDirectoryPath.getPathFile())
+          .addEnvironmentVariables(environment)
+          .setTimeout(timeoutMillis)
+          .setQuiet(quiet)
+          .execute();
+    }
   }
 
   @Override
diff --git a/src/main/java/com/google/devtools/build/lib/remote/RemoteRepositoryRemoteExecutor.java b/src/main/java/com/google/devtools/build/lib/remote/RemoteRepositoryRemoteExecutor.java
index 5c611fb..ebdffd4 100644
--- a/src/main/java/com/google/devtools/build/lib/remote/RemoteRepositoryRemoteExecutor.java
+++ b/src/main/java/com/google/devtools/build/lib/remote/RemoteRepositoryRemoteExecutor.java
@@ -25,6 +25,9 @@
 import com.google.common.collect.ImmutableSortedMap;
 import com.google.common.collect.Maps;
 import com.google.devtools.build.lib.analysis.platform.PlatformUtils;
+import com.google.devtools.build.lib.profiler.Profiler;
+import com.google.devtools.build.lib.profiler.ProfilerTask;
+import com.google.devtools.build.lib.profiler.SilentCloseable;
 import com.google.devtools.build.lib.remote.common.RemoteCacheClient.ActionKey;
 import com.google.devtools.build.lib.remote.merkletree.MerkleTree;
 import com.google.devtools.build.lib.remote.util.DigestUtil;
@@ -66,21 +69,24 @@
 
   private ExecutionResult downloadOutErr(ActionResult result)
       throws IOException, InterruptedException {
-    byte[] stdout = new byte[0];
-    if (!result.getStdoutRaw().isEmpty()) {
-      stdout = result.getStdoutRaw().toByteArray();
-    } else if (result.hasStdoutDigest()) {
-      stdout = Utils.getFromFuture(remoteCache.downloadBlob(result.getStdoutDigest()));
-    }
+    try (SilentCloseable c =
+        Profiler.instance().profile(ProfilerTask.REMOTE_DOWNLOAD, "download stdout/stderr")) {
+      byte[] stdout = new byte[0];
+      if (!result.getStdoutRaw().isEmpty()) {
+        stdout = result.getStdoutRaw().toByteArray();
+      } else if (result.hasStdoutDigest()) {
+        stdout = Utils.getFromFuture(remoteCache.downloadBlob(result.getStdoutDigest()));
+      }
 
-    byte[] stderr = new byte[0];
-    if (!result.getStderrRaw().isEmpty()) {
-      stderr = result.getStderrRaw().toByteArray();
-    } else if (result.hasStderrDigest()) {
-      stderr = Utils.getFromFuture(remoteCache.downloadBlob(result.getStderrDigest()));
-    }
+      byte[] stderr = new byte[0];
+      if (!result.getStderrRaw().isEmpty()) {
+        stderr = result.getStderrRaw().toByteArray();
+      } else if (result.hasStderrDigest()) {
+        stderr = Utils.getFromFuture(remoteCache.downloadBlob(result.getStderrDigest()));
+      }
 
-    return new ExecutionResult(result.getExitCode(), stdout, stderr);
+      return new ExecutionResult(result.getExitCode(), stdout, stderr);
+    }
   }
 
   @Override
@@ -109,23 +115,33 @@
               commandHash, merkleTree.getRootDigest(), timeout, acceptCached);
       Digest actionDigest = digestUtil.compute(action);
       ActionKey actionKey = new ActionKey(actionDigest);
-      ActionResult actionResult =
-          remoteCache.downloadActionResult(actionKey, /* inlineOutErr= */ true);
+      ActionResult actionResult;
+      try (SilentCloseable c =
+          Profiler.instance().profile(ProfilerTask.REMOTE_CACHE_CHECK, "check cache hit")) {
+        actionResult = remoteCache.downloadActionResult(actionKey, /* inlineOutErr= */ true);
+      }
       if (actionResult == null || actionResult.getExitCode() != 0) {
-        Map<Digest, Message> additionalInputs = Maps.newHashMapWithExpectedSize(2);
-        additionalInputs.put(actionDigest, action);
-        additionalInputs.put(commandHash, command);
-        remoteCache.ensureInputsPresent(merkleTree, additionalInputs);
+        try (SilentCloseable c =
+            Profiler.instance().profile(ProfilerTask.UPLOAD_TIME, "upload missing inputs")) {
+          Map<Digest, Message> additionalInputs = Maps.newHashMapWithExpectedSize(2);
+          additionalInputs.put(actionDigest, action);
+          additionalInputs.put(commandHash, command);
 
-        ExecuteRequest executeRequest =
-            ExecuteRequest.newBuilder()
-                .setActionDigest(actionDigest)
-                .setInstanceName(remoteInstanceName)
-                .setSkipCacheLookup(!acceptCached)
-                .build();
+          remoteCache.ensureInputsPresent(merkleTree, additionalInputs);
+        }
 
-        ExecuteResponse response = remoteExecutor.executeRemotely(executeRequest);
-        actionResult = response.getResult();
+        try (SilentCloseable c =
+            Profiler.instance().profile(ProfilerTask.REMOTE_EXECUTION, "execute remotely")) {
+          ExecuteRequest executeRequest =
+              ExecuteRequest.newBuilder()
+                  .setActionDigest(actionDigest)
+                  .setInstanceName(remoteInstanceName)
+                  .setSkipCacheLookup(!acceptCached)
+                  .build();
+
+          ExecuteResponse response = remoteExecutor.executeRemotely(executeRequest);
+          actionResult = response.getResult();
+        }
       }
       return downloadOutErr(actionResult);
     } finally {
diff --git a/src/test/java/com/google/devtools/build/lib/buildtool/util/BUILD b/src/test/java/com/google/devtools/build/lib/buildtool/util/BUILD
index 325eb04..232cf9b 100644
--- a/src/test/java/com/google/devtools/build/lib/buildtool/util/BUILD
+++ b/src/test/java/com/google/devtools/build/lib/buildtool/util/BUILD
@@ -29,7 +29,6 @@
     name = "util_internal",
     srcs = glob(["*.java"]),
     deps = [
-        "//java/com/google/devtools/build/lib/blaze/google/logging:google-log-handler-querier",
         "//src/main/java/com/google/devtools/build/lib:build",
         "//src/main/java/com/google/devtools/build/lib:build-request-options",
         "//src/main/java/com/google/devtools/build/lib:keep-going-option",