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