1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Copyright (C) 2009 The Android Open Source Project 3282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 4282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 5282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * you may not use this file except in compliance with the License. 6282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * You may obtain a copy of the License at 7282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 8282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 9282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 10282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Unless required by applicable law or agreed to in writing, software 11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 12282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * See the License for the specific language governing permissions and 14282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * limitations under the License. 15282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 16282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 17282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.io.IOException; 18282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.io.FileReader; 19282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.io.BufferedReader; 20282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.io.PrintStream; 21282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.util.Set; 22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.util.TreeSet; 23282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.util.HashSet; 24282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.util.Iterator; 25282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 26282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/** 27282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Prints HTML containing removed and added files. 28282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 29282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskipublic class PrintHtmlDiff { 30282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 31282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private static final String OLD_PRELOADED_CLASSES 32282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski = "old-preloaded-classes"; 33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public static void main(String[] args) throws IOException, 35282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ClassNotFoundException { 36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Root root = Root.fromFile(args[0]); 37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski BufferedReader oldClasses = new BufferedReader( 39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski new FileReader(OLD_PRELOADED_CLASSES)); 40282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 41282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Classes loaded implicitly by the zygote. 42282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Set<LoadedClass> zygote = new HashSet<LoadedClass>(); 43282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (Proc proc : root.processes.values()) { 44282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (proc.name.equals("zygote")) { 45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (Operation op : proc.operations) { 46282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski zygote.add(op.loadedClass); 47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Set<LoadedClass> removed = new TreeSet<LoadedClass>(); 53282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Set<LoadedClass> added = new TreeSet<LoadedClass>(); 54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 55282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (LoadedClass loadedClass : root.loadedClasses.values()) { 56282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (loadedClass.preloaded && !zygote.contains(loadedClass)) { 57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski added.add(loadedClass); 58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 59282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String line; 62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while ((line = oldClasses.readLine()) != null) { 63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski line = line.trim(); 64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski LoadedClass clazz = root.loadedClasses.get(line); 65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (clazz != null) { 66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski added.remove(clazz); 67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!clazz.preloaded) removed.add(clazz); 68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski PrintStream out = System.out; 72282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski out.println("<html><body>"); 74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski out.println("<style>"); 75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski out.println("a, th, td, h2 { font-family: arial }"); 76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski out.println("th, td { font-size: small }"); 77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski out.println("</style>"); 78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski out.println("<script src=\"sorttable.js\"></script>"); 79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski out.println("<p><a href=\"#removed\">Removed</a>"); 80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski out.println("<a name=\"added\"/><h2>Added</h2>"); 81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printTable(out, root.baseline, added); 82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski out.println("<a name=\"removed\"/><h2>Removed</h2>"); 83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printTable(out, root.baseline, removed); 84282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski out.println("</body></html>"); 85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski static void printTable(PrintStream out, MemoryUsage baseline, 88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Iterable<LoadedClass> classes) { 89282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski out.println("<table border=\"1\" cellpadding=\"5\"" 90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski + " class=\"sortable\">"); 91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski out.println("<thead><tr>"); 93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski out.println("<th>Name</th>"); 94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski out.println("<th>Load Time (us)</th>"); 95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski out.println("<th>Loaded By</th>"); 96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski out.println("<th>Heap (B)</th>"); 97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski out.println("<th>Pages</th>"); 98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski out.println("</tr></thead>"); 99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (LoadedClass clazz : classes) { 101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski out.println("<tr>"); 102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski out.println("<td>" + clazz.name + "</td>"); 103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski out.println("<td>" + clazz.medianTimeMicros() + "</td>"); 104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski out.println("<td>"); 106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Set<String> procNames = new TreeSet<String>(); 107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (Operation op : clazz.loads) procNames.add(op.process.name); 108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (Operation op : clazz.initializations) { 109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski procNames.add(op.process.name); 110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (procNames.size() <= 3) { 112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (String name : procNames) { 113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski out.print(name + "<br/>"); 114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Iterator<String> i = procNames.iterator(); 117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski out.print(i.next() + "<br/>"); 118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski out.print(i.next() + "<br/>"); 119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski out.print("...and " + (procNames.size() - 2) 120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski + " others."); 121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski out.println("</td>"); 123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (clazz.memoryUsage.isAvailable()) { 125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski MemoryUsage subtracted 126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski = clazz.memoryUsage.subtract(baseline); 127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski out.println("<td>" + (subtracted.javaHeapSize() 129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski + subtracted.nativeHeapSize) + "</td>"); 130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski out.println("<td>" + subtracted.totalPages() + "</td>"); 131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (int i = 0; i < 2; i++) { 133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski out.println("<td>n/a</td>"); 134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski out.println("</tr>"); 138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski out.println("</table>"); 141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 143