Improve efficiency of DexBuilder actions:
- don't use more CPUs than are available
- buffer writes to the output zip; currently it calls write(2) every 50 bytes on average

PiperOrigin-RevId: 334184098
diff --git a/src/tools/android/java/com/google/devtools/build/android/r8/CompatDexBuilder.java b/src/tools/android/java/com/google/devtools/build/android/r8/CompatDexBuilder.java
index 148450a..10be42b 100644
--- a/src/tools/android/java/com/google/devtools/build/android/r8/CompatDexBuilder.java
+++ b/src/tools/android/java/com/google/devtools/build/android/r8/CompatDexBuilder.java
@@ -14,6 +14,7 @@
 package com.google.devtools.build.android.r8;
 
 import static com.google.common.base.Verify.verify;
+import static java.lang.Math.min;
 import static java.nio.charset.StandardCharsets.UTF_8;
 
 import com.android.tools.r8.ByteDataView;
@@ -26,6 +27,7 @@
 import com.android.tools.r8.origin.ArchiveEntryOrigin;
 import com.android.tools.r8.origin.PathOrigin;
 import com.google.common.io.ByteStreams;
+import java.io.BufferedOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.file.Files;
@@ -73,7 +75,7 @@
 
   private String input;
   private String output;
-  private int numberOfThreads = 8;
+  private int numberOfThreads = min(8, Runtime.getRuntime().availableProcessors());
   private boolean noLocals;
 
   public static void main(String[] args)
@@ -141,7 +143,8 @@
     }
 
     ExecutorService executor = Executors.newWorkStealingPool(numberOfThreads);
-    try (ZipOutputStream out = new ZipOutputStream(Files.newOutputStream(Paths.get(output)))) {
+    try (ZipOutputStream out =
+        new ZipOutputStream(new BufferedOutputStream(Files.newOutputStream(Paths.get(output))))) {
 
       List<ZipEntry> toDex = new ArrayList<>();