Update memory info to use only Runtime.totalMemory and freeMemory.

Change-Id: I47df1eae08a6247e87a333044dc0da2a17995f62
diff --git a/src/main/java/com/android/tools/r8/utils/Timing.java b/src/main/java/com/android/tools/r8/utils/Timing.java
index df575a6..7d68954 100644
--- a/src/main/java/com/android/tools/r8/utils/Timing.java
+++ b/src/main/java/com/android/tools/r8/utils/Timing.java
@@ -13,13 +13,9 @@
 // Finally a report is printed by:
 //     t.report();
 
-import java.lang.management.ManagementFactory;
-import java.lang.management.MemoryMXBean;
-import java.lang.management.MemoryPoolMXBean;
-import java.util.ArrayList;
 import java.util.LinkedHashMap;
-import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Stack;
 
 public class Timing {
@@ -41,29 +37,45 @@
     stack.push(new Node("Recorded timings for " + title));
   }
 
+  private static class MemInfo {
+    final long used;
+
+    MemInfo(long used) {
+      this.used = used;
+    }
+
+    public static MemInfo fromTotalAndFree(long total, long free) {
+      return new MemInfo(total - free);
+    }
+
+    long usedDelta(MemInfo previous) {
+      return used - previous.used;
+    }
+  }
+
   class Node {
     final String title;
 
     final Map<String, Node> children = new LinkedHashMap<>();
     long duration = 0;
     long start_time;
-    List<String> startMemory;
-    List<String> endMemory;
+    Map<String, MemInfo> startMemory;
+    Map<String, MemInfo> endMemory;
 
     Node(String title) {
       this.title = title;
-      this.start_time = System.nanoTime();
       if (trackMemory) {
         startMemory = computeMemoryInformation();
       }
+      this.start_time = System.nanoTime();
     }
 
     void restart() {
       assert start_time == -1;
-      start_time = System.nanoTime();
       if (trackMemory) {
         startMemory = computeMemoryInformation();
       }
+      start_time = System.nanoTime();
     }
 
     void end() {
@@ -71,7 +83,6 @@
       start_time = -1;
       assert duration() >= 0;
       if (trackMemory) {
-        System.gc();
         endMemory = computeMemoryInformation();
       }
     }
@@ -82,13 +93,12 @@
 
     @Override
     public String toString() {
-      return title + ": " + (duration() / 1000000) + "ms.";
+      return title + ": " + prettyTime(duration());
     }
 
     public String toString(Node top) {
       if (this == top) return toString();
-      long percentage = duration() * 100 / top.duration();
-      return toString() + " (" + percentage + "%)";
+      return toString() + " (" + prettyPercentage(duration(), top.duration()) + ")";
     }
 
     public void report(int depth, Node top) {
@@ -100,44 +110,64 @@
         System.out.print("- ");
       }
       System.out.println(toString(top));
-      System.out.println();
       if (trackMemory) {
-        printMemoryStart(depth);
-        System.out.println();
+        printMemory(depth);
       }
       children.values().forEach(p -> p.report(depth + 1, top));
-      if (trackMemory) {
-        printMemoryEnd(depth);
-        System.out.println();
-      }
     }
 
-    private void printMemoryStart(int depth) {
-      if (startMemory != null) {
-        printMemory(depth, title + "(Memory) Start: ", startMemory);
-      }
-    }
-
-    private void printMemoryEnd(int depth) {
-      if (endMemory != null) {
-        printMemory(depth, title + "(Memory) End: ", endMemory);
-      }
-    }
-
-    private void printMemory(int depth, String header, List<String> strings) {
-      for (int i = 0; i <= depth; i++) {
-        System.out.print("  ");
-      }
-      System.out.println(header);
-      for (String memoryInfo : strings) {
-        for (int i = 0; i <= depth; i++) {
-          System.out.print("  ");
+    private void printMemory(int depth) {
+      for (Entry<String, MemInfo> start : startMemory.entrySet()) {
+        if (start.getKey().equals("Memory")) {
+          for (int i = 0; i <= depth; i++) {
+            System.out.print("  ");
+          }
+          MemInfo endValue = endMemory.get(start.getKey());
+          MemInfo startValue = start.getValue();
+          System.out.println(
+              start.getKey()
+                  + " start: "
+                  + prettySize(startValue.used)
+                  + ", end: "
+                  + prettySize(endValue.used)
+                  + ", delta: "
+                  + prettySize(endValue.usedDelta(startValue)));
         }
-        System.out.println(memoryInfo);
       }
     }
   }
 
+  private static String prettyPercentage(long part, long total) {
+    return (part * 100 / total) + "%";
+  }
+
+  private static String prettyTime(long value) {
+    return (value / 1000000) + "ms";
+  }
+
+  private static String prettySize(long value) {
+    return prettyNumber(value / 1024) + "k";
+  }
+
+  private static String prettyNumber(long value) {
+    String printed = "" + Math.abs(value);
+    if (printed.length() < 4) {
+      return "" + value;
+    }
+    StringBuilder builder = new StringBuilder();
+    if (value < 0) {
+      builder.append('-');
+    }
+    int prefix = printed.length() % 3;
+    builder.append(printed, 0, prefix);
+    for (int i = prefix; i < printed.length(); i += 3) {
+      if (i > 0) {
+        builder.append('.');
+      }
+      builder.append(printed, i, i + 3);
+    }
+    return builder.toString();
+  }
 
   public void begin(String title) {
     Node parent = stack.peek();
@@ -177,22 +207,13 @@
     void apply();
   }
 
-  private List<String> computeMemoryInformation() {
-    List<String> strings = new ArrayList<>();
-    strings.add(
-        "Free memory: "
-            + Runtime.getRuntime().freeMemory()
-            + "\tTotal memory: "
-            + Runtime.getRuntime().totalMemory()
-            + "\tMax memory: "
-            + Runtime.getRuntime().maxMemory());
-    MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
-    strings.add("Heap summary: " + memoryMXBean.getHeapMemoryUsage().toString());
-    strings.add("Non-heap summary: " + memoryMXBean.getNonHeapMemoryUsage().toString());
-    // Print out the memory information for all managed memory pools.
-    for (MemoryPoolMXBean memoryPoolMXBean : ManagementFactory.getMemoryPoolMXBeans()) {
-      strings.add(memoryPoolMXBean.getName() + ": " + memoryPoolMXBean.getUsage().toString());
-    }
-    return strings;
+  private Map<String, MemInfo> computeMemoryInformation() {
+    System.gc();
+    Map<String, MemInfo> info = new LinkedHashMap<>();
+    info.put(
+        "Memory",
+        MemInfo.fromTotalAndFree(
+            Runtime.getRuntime().totalMemory(), Runtime.getRuntime().freeMemory()));
+    return info;
   }
 }