| /* |
| * Copyright (C) 2009 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| import java.io.IOException; |
| import java.io.FileReader; |
| import java.io.BufferedReader; |
| import java.io.PrintStream; |
| import java.util.Set; |
| import java.util.TreeSet; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| |
| /** |
| * Prints HTML containing removed and added files. |
| */ |
| public class PrintHtmlDiff { |
| |
| private static final String OLD_PRELOADED_CLASSES |
| = "old-preloaded-classes"; |
| |
| public static void main(String[] args) throws IOException, |
| ClassNotFoundException { |
| Root root = Root.fromFile(args[0]); |
| |
| BufferedReader oldClasses = new BufferedReader( |
| new FileReader(OLD_PRELOADED_CLASSES)); |
| |
| // Classes loaded implicitly by the zygote. |
| Set<LoadedClass> zygote = new HashSet<LoadedClass>(); |
| for (Proc proc : root.processes.values()) { |
| if (proc.name.equals("zygote")) { |
| for (Operation op : proc.operations) { |
| zygote.add(op.loadedClass); |
| } |
| break; |
| } |
| } |
| |
| Set<LoadedClass> removed = new TreeSet<LoadedClass>(); |
| Set<LoadedClass> added = new TreeSet<LoadedClass>(); |
| |
| for (LoadedClass loadedClass : root.loadedClasses.values()) { |
| if (loadedClass.preloaded && !zygote.contains(loadedClass)) { |
| added.add(loadedClass); |
| } |
| } |
| |
| String line; |
| while ((line = oldClasses.readLine()) != null) { |
| line = line.trim(); |
| LoadedClass clazz = root.loadedClasses.get(line); |
| if (clazz != null) { |
| added.remove(clazz); |
| if (!clazz.preloaded) removed.add(clazz); |
| } |
| } |
| |
| PrintStream out = System.out; |
| |
| out.println("<html><body>"); |
| out.println("<style>"); |
| out.println("a, th, td, h2 { font-family: arial }"); |
| out.println("th, td { font-size: small }"); |
| out.println("</style>"); |
| out.println("<script src=\"sorttable.js\"></script>"); |
| out.println("<p><a href=\"#removed\">Removed</a>"); |
| out.println("<a name=\"added\"/><h2>Added</h2>"); |
| printTable(out, root.baseline, added); |
| out.println("<a name=\"removed\"/><h2>Removed</h2>"); |
| printTable(out, root.baseline, removed); |
| out.println("</body></html>"); |
| } |
| |
| static void printTable(PrintStream out, MemoryUsage baseline, |
| Iterable<LoadedClass> classes) { |
| out.println("<table border=\"1\" cellpadding=\"5\"" |
| + " class=\"sortable\">"); |
| |
| out.println("<thead><tr>"); |
| out.println("<th>Name</th>"); |
| out.println("<th>Load Time (us)</th>"); |
| out.println("<th>Loaded By</th>"); |
| out.println("<th>Heap (B)</th>"); |
| out.println("<th>Pages</th>"); |
| out.println("</tr></thead>"); |
| |
| for (LoadedClass clazz : classes) { |
| out.println("<tr>"); |
| out.println("<td>" + clazz.name + "</td>"); |
| out.println("<td>" + clazz.medianTimeMicros() + "</td>"); |
| |
| out.println("<td>"); |
| Set<String> procNames = new TreeSet<String>(); |
| for (Operation op : clazz.loads) procNames.add(op.process.name); |
| for (Operation op : clazz.initializations) { |
| procNames.add(op.process.name); |
| } |
| if (procNames.size() <= 3) { |
| for (String name : procNames) { |
| out.print(name + "<br/>"); |
| } |
| } else { |
| Iterator<String> i = procNames.iterator(); |
| out.print(i.next() + "<br/>"); |
| out.print(i.next() + "<br/>"); |
| out.print("...and " + (procNames.size() - 2) |
| + " others."); |
| } |
| out.println("</td>"); |
| |
| if (clazz.memoryUsage.isAvailable()) { |
| MemoryUsage subtracted |
| = clazz.memoryUsage.subtract(baseline); |
| |
| out.println("<td>" + (subtracted.javaHeapSize() |
| + subtracted.nativeHeapSize) + "</td>"); |
| out.println("<td>" + subtracted.totalPages() + "</td>"); |
| } else { |
| for (int i = 0; i < 2; i++) { |
| out.println("<td>n/a</td>"); |
| } |
| } |
| |
| out.println("</tr>"); |
| } |
| |
| out.println("</table>"); |
| } |
| } |