Add a option to disable idle gc.

If a Bazel server is idle for 10 seconds, it unconditionally triggers a full-scale Java GC via System.gc(). This behavior doesn't have clear benefits and causes Bazel to steal resources from whatever the user does after invoking Bazel. This CL adds a startup option, --idle_server_tasks, to toggle the idle GC behavior.

Also, add some logging for when idle GC is enabled, so it's easier to evaluate its effects. Example of logging:
```
180718 17:43:04.609:I 247 [com.google.devtools.build.lib.server.IdleServerTasks.lambda$idle$0] [Idle GC] used: 157MB -> 15MB, committed: 421MB -> 422MB
```

Fixes https://github.com/bazelbuild/bazel/issues/5589.

Closes #5628.

PiperOrigin-RevId: 207869996
diff --git a/src/main/java/com/google/devtools/build/lib/server/IdleServerTasks.java b/src/main/java/com/google/devtools/build/lib/server/IdleServerTasks.java
index 01e596a..d8cb41a 100644
--- a/src/main/java/com/google/devtools/build/lib/server/IdleServerTasks.java
+++ b/src/main/java/com/google/devtools/build/lib/server/IdleServerTasks.java
@@ -16,6 +16,10 @@
 
 import com.google.common.base.Preconditions;
 import com.google.devtools.build.lib.profiler.AutoProfiler;
+import com.google.devtools.build.lib.util.StringUtilities;
+import java.lang.management.ManagementFactory;
+import java.lang.management.MemoryMXBean;
+import java.lang.management.MemoryUsage;
 import java.util.concurrent.Future;
 import java.util.concurrent.ScheduledThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
@@ -29,9 +33,7 @@
   private final ScheduledThreadPoolExecutor executor;
   private static final Logger logger = Logger.getLogger(IdleServerTasks.class.getName());
 
-  /**
-   * Must be called from the main thread.
-   */
+  /** Must be called from the main thread. */
   public IdleServerTasks() {
     this.executor = new ScheduledThreadPoolExecutor(1);
   }
@@ -43,14 +45,23 @@
   public void idle() {
     Preconditions.checkState(!executor.isShutdown());
 
-    // Do a GC cycle while the server is idle.
     @SuppressWarnings("unused")
     Future<?> possiblyIgnoredError =
         executor.schedule(
             () -> {
+              MemoryMXBean memBean = ManagementFactory.getMemoryMXBean();
+              MemoryUsage before = memBean.getHeapMemoryUsage();
               try (AutoProfiler p = AutoProfiler.logged("Idle GC", logger)) {
                 System.gc();
               }
+              MemoryUsage after = memBean.getHeapMemoryUsage();
+              logger.info(
+                  String.format(
+                      "[Idle GC] used: %s -> %s, committed: %s -> %s",
+                      StringUtilities.prettyPrintBytes(before.getUsed()),
+                      StringUtilities.prettyPrintBytes(after.getUsed()),
+                      StringUtilities.prettyPrintBytes(before.getCommitted()),
+                      StringUtilities.prettyPrintBytes(after.getCommitted())));
             },
             10,
             TimeUnit.SECONDS);