Add --dist-one flag to the benchmark script to make it copy a single set of build metrics to a dist dir.

Change-Id: Id392a33c42fed6c5014b2fd5dd69fa80fa0d9f0f
diff --git a/tools/perf/benchmarks b/tools/perf/benchmarks
index 0a126e6..f46b920 100755
--- a/tools/perf/benchmarks
+++ b/tools/perf/benchmarks
@@ -295,11 +295,16 @@
             ns = self._run_build(lunch, benchmark_log_dir.joinpath("measured"), benchmark.modules)
             report.duration_ns = ns
 
-            # Postroll builds
-            for i in range(benchmark.preroll):
-                ns = self._run_build(lunch, benchmark_log_dir.joinpath(f"post_{i}"),
-                                     benchmark.modules)
-                report.postroll_duration_ns.append(ns)
+            dist_one = self._options.DistOne()
+            if dist_one:
+                # If we're disting just one benchmark, save the logs and we can stop here.
+                self._dist(dist_one)
+            else:
+                # Postroll builds
+                for i in range(benchmark.preroll):
+                    ns = self._run_build(lunch, benchmark_log_dir.joinpath(f"post_{i}"),
+                                         benchmark.modules)
+                    report.postroll_duration_ns.append(ns)
 
         finally:
             # Always undo, even if we crashed or the build failed and we stopped.
@@ -348,6 +353,22 @@
 
         return after_ns - before_ns
 
+    def _dist(self, dist_dir):
+        out_dir = pathlib.Path("out")
+        dest_dir = pathlib.Path(dist_dir).joinpath("logs")
+        os.makedirs(dest_dir, exist_ok=True)
+        basenames = [
+            "build.trace.gz",
+            "soong.log",
+            "soong_build_metrics.pb",
+            "soong_metrics",
+        ]
+        for base in basenames:
+            src = out_dir.joinpath(base)
+            if src.exists():
+                sys.stderr.write(f"DIST: copied {src} to {dest_dir}\n")
+                shutil.copy(src, dest_dir)
+
     def _write_summary(self):
         # Write the results, even if the build failed or we crashed, including
         # whether we finished all of the benchmarks.
@@ -439,6 +460,9 @@
         parser.add_argument("--benchmark", nargs="*", default=[b.id for b in self._benchmarks],
                             metavar="BENCHMARKS",
                             help="Benchmarks to run.  Default suite will be run if omitted.")
+        parser.add_argument("--dist-one", type=str,
+                            help="Copy logs and metrics to the given dist dir. Requires that only"
+                                + " one benchmark be supplied. Postroll steps will be skipped.")
 
         self._args = parser.parse_args()
 
@@ -453,6 +477,10 @@
             for id in bad_ids:
                 self._error(f"Invalid benchmark: {id}")
 
+        # --dist-one requires that only one benchmark be supplied
+        if len(self.Benchmarks()) != 1:
+            self._error("--dist-one requires that exactly one --benchmark.")
+
         if self._had_error:
             raise FatalError()
 
@@ -534,6 +562,9 @@
     def Iterations(self):
         return self._args.iterations
 
+    def DistOne(self):
+        return self._args.dist_one
+
     def _init_benchmarks(self):
         """Initialize the list of benchmarks."""
         # Assumes that we've already chdired to the root of the tree.