Fix profiler slow task limiting

Looks like a typo resulted in getSlowestTasks accumulating way more than it
should have and we were missing the test coverage to catch it.

RELNOTES: None
PiperOrigin-RevId: 194169355
diff --git a/src/main/java/com/google/devtools/build/lib/profiler/Profiler.java b/src/main/java/com/google/devtools/build/lib/profiler/Profiler.java
index e9113ce..233f374 100644
--- a/src/main/java/com/google/devtools/build/lib/profiler/Profiler.java
+++ b/src/main/java/com/google/devtools/build/lib/profiler/Profiler.java
@@ -369,7 +369,7 @@
     // @ThreadSafe
     Iterable<SlowTask> getSlowestTasks() {
       // This is slow, but since it only happens during the end of the invocation, it's OK
-      Extrema mergedExtrema = Extrema.max(size * SHARDS);
+      Extrema<SlowTask> mergedExtrema = Extrema.max(size);
       for (int i = 0; i < SHARDS; i++) {
         Extrema<SlowTask> extrema = extremaAggregators[i];
         synchronized (extrema) {
diff --git a/src/test/java/com/google/devtools/build/lib/profiler/ProfilerTest.java b/src/test/java/com/google/devtools/build/lib/profiler/ProfilerTest.java
index ffc7e7f..a3e7993 100644
--- a/src/test/java/com/google/devtools/build/lib/profiler/ProfilerTest.java
+++ b/src/test/java/com/google/devtools/build/lib/profiler/ProfilerTest.java
@@ -17,9 +17,12 @@
 import static java.nio.charset.StandardCharsets.ISO_8859_1;
 import static org.junit.Assert.fail;
 
+import com.google.common.collect.ImmutableList;
+import com.google.common.io.ByteStreams;
 import com.google.devtools.build.lib.clock.BlazeClock;
 import com.google.devtools.build.lib.clock.Clock;
 import com.google.devtools.build.lib.profiler.Profiler.ProfiledTaskKinds;
+import com.google.devtools.build.lib.profiler.Profiler.SlowTask;
 import com.google.devtools.build.lib.profiler.analysis.ProfileInfo;
 import com.google.devtools.build.lib.testutil.FoundationTestCase;
 import com.google.devtools.build.lib.testutil.ManualClock;
@@ -29,7 +32,9 @@
 import com.google.devtools.build.lib.vfs.Path;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.zip.Deflater;
 import java.util.zip.DeflaterOutputStream;
@@ -201,6 +206,37 @@
   }
 
   @Test
+  public void testGetSlowestTasksCapped() throws Exception {
+    profiler.start(
+        ProfiledTaskKinds.SLOWEST,
+        ByteStreams.nullOutputStream(),
+        "test",
+        /*recordAllDurations=*/ true,
+        BlazeClock.instance(),
+        BlazeClock.instance().nanoTime());
+
+    List<Long> expectedSlowestDurations = new ArrayList<>();
+    for (int i = 0; i < ProfilerTask.VFS_STAT.slowestInstancesCount; i++) {
+      long fakeDuration = i + 1000;
+      profiler.logSimpleTask(1, fakeDuration + 1, ProfilerTask.VFS_STAT, "stat");
+      expectedSlowestDurations.add(fakeDuration);
+    }
+
+    // Sprinkle in a whole bunch of fast tasks.
+    for (int i = 0; i < 100; i++) {
+      profiler.logSimpleTask(1, i + 1, ProfilerTask.VFS_STAT, "stat" + i);
+    }
+
+    ImmutableList<SlowTask> slowTasks = ImmutableList.copyOf(profiler.getSlowestTasks());
+    assertThat(slowTasks).hasSize(ProfilerTask.VFS_STAT.slowestInstancesCount);
+
+    ImmutableList<Long> slowestDurations = slowTasks.stream()
+        .map(task -> task.getDurationNanos())
+        .collect(ImmutableList.toImmutableList());
+    assertThat(slowestDurations).containsExactlyElementsIn(expectedSlowestDurations);
+  }
+
+  @Test
   public void testProfilerRecordsNothing() throws Exception {
     Path profileData = cacheDir.getRelative("foo");