1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 import java.io.IOException; 18 import java.io.FileReader; 19 import java.io.BufferedReader; 20 import java.io.PrintStream; 21 import java.util.Set; 22 import java.util.TreeSet; 23 import java.util.HashSet; 24 import java.util.Iterator; 25 26 /** 27 * Prints HTML containing removed and added files. 28 */ 29 public class PrintHtmlDiff { 30 31 private static final String OLD_PRELOADED_CLASSES 32 = "old-preloaded-classes"; 33 main(String[] args)34 public static void main(String[] args) throws IOException, 35 ClassNotFoundException { 36 Root root = Root.fromFile(args[0]); 37 38 BufferedReader oldClasses = new BufferedReader( 39 new FileReader(OLD_PRELOADED_CLASSES)); 40 41 // Classes loaded implicitly by the zygote. 42 Set<LoadedClass> zygote = new HashSet<LoadedClass>(); 43 for (Proc proc : root.processes.values()) { 44 if (proc.name.equals("zygote")) { 45 for (Operation op : proc.operations) { 46 zygote.add(op.loadedClass); 47 } 48 break; 49 } 50 } 51 52 Set<LoadedClass> removed = new TreeSet<LoadedClass>(); 53 Set<LoadedClass> added = new TreeSet<LoadedClass>(); 54 55 for (LoadedClass loadedClass : root.loadedClasses.values()) { 56 if (loadedClass.preloaded && !zygote.contains(loadedClass)) { 57 added.add(loadedClass); 58 } 59 } 60 61 String line; 62 while ((line = oldClasses.readLine()) != null) { 63 line = line.trim(); 64 LoadedClass clazz = root.loadedClasses.get(line); 65 if (clazz != null) { 66 added.remove(clazz); 67 if (!clazz.preloaded) removed.add(clazz); 68 } 69 } 70 71 PrintStream out = System.out; 72 73 out.println("<html><body>"); 74 out.println("<style>"); 75 out.println("a, th, td, h2 { font-family: arial }"); 76 out.println("th, td { font-size: small }"); 77 out.println("</style>"); 78 out.println("<script src=\"sorttable.js\"></script>"); 79 out.println("<p><a href=\"#removed\">Removed</a>"); 80 out.println("<a name=\"added\"/><h2>Added</h2>"); 81 printTable(out, root.baseline, added); 82 out.println("<a name=\"removed\"/><h2>Removed</h2>"); 83 printTable(out, root.baseline, removed); 84 out.println("</body></html>"); 85 } 86 printTable(PrintStream out, MemoryUsage baseline, Iterable<LoadedClass> classes)87 static void printTable(PrintStream out, MemoryUsage baseline, 88 Iterable<LoadedClass> classes) { 89 out.println("<table border=\"1\" cellpadding=\"5\"" 90 + " class=\"sortable\">"); 91 92 out.println("<thead><tr>"); 93 out.println("<th>Name</th>"); 94 out.println("<th>Load Time (us)</th>"); 95 out.println("<th>Loaded By</th>"); 96 out.println("<th>Heap (B)</th>"); 97 out.println("<th>Pages</th>"); 98 out.println("</tr></thead>"); 99 100 for (LoadedClass clazz : classes) { 101 out.println("<tr>"); 102 out.println("<td>" + clazz.name + "</td>"); 103 out.println("<td>" + clazz.medianTimeMicros() + "</td>"); 104 105 out.println("<td>"); 106 Set<String> procNames = new TreeSet<String>(); 107 for (Operation op : clazz.loads) procNames.add(op.process.name); 108 for (Operation op : clazz.initializations) { 109 procNames.add(op.process.name); 110 } 111 if (procNames.size() <= 3) { 112 for (String name : procNames) { 113 out.print(name + "<br/>"); 114 } 115 } else { 116 Iterator<String> i = procNames.iterator(); 117 out.print(i.next() + "<br/>"); 118 out.print(i.next() + "<br/>"); 119 out.print("...and " + (procNames.size() - 2) 120 + " others."); 121 } 122 out.println("</td>"); 123 124 if (clazz.memoryUsage.isAvailable()) { 125 MemoryUsage subtracted 126 = clazz.memoryUsage.subtract(baseline); 127 128 out.println("<td>" + (subtracted.javaHeapSize() 129 + subtracted.nativeHeapSize) + "</td>"); 130 out.println("<td>" + subtracted.totalPages() + "</td>"); 131 } else { 132 for (int i = 0; i < 2; i++) { 133 out.println("<td>n/a</td>"); 134 } 135 } 136 137 out.println("</tr>"); 138 } 139 140 out.println("</table>"); 141 } 142 } 143