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