Adjusts the SOYC dashboard to include a size breakdown of the
initial download.
Review by: knorton
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@5298 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/tools/soyc-vis/build.xml b/tools/soyc-vis/build.xml
index c6d929d..6650e54 100644
--- a/tools/soyc-vis/build.xml
+++ b/tools/soyc-vis/build.xml
@@ -5,6 +5,9 @@
<property name="gwt.root" location="../.." />
<property name="project.tail" value="tools/soyc-vis" />
<import file="${gwt.root}/common.ant.xml" />
+
+ <!-- Platform shouldn't matter here, just picking one -->
+ <property.ensure name="gwt.dev.jar" location="${gwt.build.lib}/gwt-dev-linux.jar" />
<target name="clean">
<delete dir="build"/>
@@ -12,7 +15,11 @@
<target name="compile">
<mkdir dir="${javac.out}"/>
- <javac srcdir="src" destdir="${javac.out}"/>
+ <javac srcdir="src" destdir="${javac.out}">
+ <classpath>
+ <pathelement location="${gwt.dev.jar}" />
+ </classpath>
+ </javac>
<mkdir dir="${javac.out}/images"/>
<copy todir="${javac.out}/images">
<fileset dir="images"/>
diff --git a/tools/soyc-vis/src/com/google/gwt/soyc/CodeCollection.java b/tools/soyc-vis/src/com/google/gwt/soyc/CodeCollection.java
index 618e303..b05fead 100644
--- a/tools/soyc-vis/src/com/google/gwt/soyc/CodeCollection.java
+++ b/tools/soyc-vis/src/com/google/gwt/soyc/CodeCollection.java
@@ -34,29 +34,13 @@
codeType = type;
}
- public float getCumPartialSize() {
+ public float getCumPartialSize(SizeBreakdown breakdown) {
cumPartialSize = 0f;
for (String className : classes) {
- if (!GlobalInformation.classToPartialSize.containsKey(className)) {
- System.err.println("*** NO PARTIAL SIZE FOUND FOR CLASS " + className
- + " *****");
- } else {
- cumPartialSize += GlobalInformation.classToPartialSize.get(className);
+ if (breakdown.classToPartialSize.containsKey(className)) {
+ cumPartialSize += breakdown.classToPartialSize.get(className);
}
}
return cumPartialSize;
}
-
- public int getCumSize() {
- cumSize = 0;
- for (String className : classes) {
- if (!GlobalInformation.classToSize.containsKey(className)) {
- System.err.println("*** NO SIZE FOUND FOR CLASS " + className
- + " *****");
- } else {
- cumSize += GlobalInformation.classToSize.get(className);
- }
- }
- return cumSize;
- }
}
diff --git a/tools/soyc-vis/src/com/google/gwt/soyc/GlobalInformation.java b/tools/soyc-vis/src/com/google/gwt/soyc/GlobalInformation.java
index e4c1f12..9e860e6 100644
--- a/tools/soyc-vis/src/com/google/gwt/soyc/GlobalInformation.java
+++ b/tools/soyc-vis/src/com/google/gwt/soyc/GlobalInformation.java
@@ -17,8 +17,9 @@
package com.google.gwt.soyc;
import java.util.HashMap;
-import java.util.TreeMap;
import java.util.HashSet;
+import java.util.Map;
+import java.util.TreeMap;
import java.util.TreeSet;
/**
@@ -29,29 +30,16 @@
public static Boolean displayDependencies = false;
public static Boolean displaySplitPoints = false;
- public static int allOtherFragmentsPartialSize = 0;
public static HashMap<String, String> classToPackage = new HashMap<String, String>();
- public static HashMap<String, Float> classToPartialSize = new HashMap<String, Float>();
- public static HashMap<String, Integer> classToSize = new HashMap<String, Integer>();
public static HashMap<String, HashSet<String>> classToWhatItDependsOn = new HashMap<String, HashSet<String>>();
- public static float cumPartialSizeFromPackages = 0f;
- public static int cumSizeAllCode = 0;
- public static int cumSizeFromPackages = 0;
- public static int cumSizeInitialFragment = 0;
- // collect only size for exclusive fragments
- public static HashMap<Integer, Float> fragmentToPartialSize = new HashMap<Integer, Float>();
+ public static HashMap<Integer, Float> fragmentToPartialSize = new HashMap<Integer, Float>();
public static HashMap<Integer, HashSet<String>> fragmentToStories = new HashMap<Integer, HashSet<String>>();
- public static TreeMap<String, LiteralsCollection> nameToLitColl = new TreeMap<String, LiteralsCollection>();
- public static HashMap<String, CodeCollection> nameToCodeColl = new HashMap<String, CodeCollection>();
- public static int nonAttributedBytes = 0;
- public static HashSet<String> nonAttributedStories = new HashSet<String>();
public static int numBytesDoubleCounted = 0;
public static int numFragments = 0;
public static int numSplitPoints = 0;
- public static TreeMap<String, TreeSet<String>> packageToClasses = new TreeMap<String, TreeSet<String>>();
- public static HashMap<String, Float> packageToPartialSize = new HashMap<String, Float>();
- public static HashMap<String, Integer> packageToSize = new HashMap<String, Integer>();
+ public static Map<String, TreeSet<String>> packageToClasses = new TreeMap<String, TreeSet<String>>();
+
public static HashMap<Integer, String> splitPointToLocation = new HashMap<Integer, String>();
public static HashMap<String, HashSet<String>> storiesToCorrClasses = new HashMap<String, HashSet<String>>();
public static HashMap<String, HashSet<String>> storiesToCorrClassesAndMethods = new HashMap<String, HashSet<String>>();
@@ -60,18 +48,35 @@
public static Settings settings = new Settings();
+ public static SizeBreakdown initialCodeBreakdown = new SizeBreakdown(
+ "Initially downloaded code", "initial");
+ public static SizeBreakdown totalCodeBreakdown = new SizeBreakdown(
+ "Total program", "total");
+
+ public static SizeBreakdown[] allSizeBreakdowns() {
+ return new SizeBreakdown[] {totalCodeBreakdown, initialCodeBreakdown};
+ }
+
public static void computePackageSizes() {
- cumSizeFromPackages = 0;
+ for (SizeBreakdown breakdown : allSizeBreakdowns()) {
+ computePackageSizes(breakdown.packageToSize, breakdown.classToSize);
+ }
+ }
+
+ public static void computePartialPackageSizes() {
+ for (SizeBreakdown breakdown : allSizeBreakdowns()) {
+ computePartialPackageSizes(breakdown.packageToPartialSize, breakdown.classToPartialSize);
+ }
+ }
+
+ private static void computePackageSizes(Map<String, Integer> packageToSize,
+ Map<String, Integer> classToSize) {
packageToSize.clear();
for (String packageName : packageToClasses.keySet()) {
packageToSize.put(packageName, 0);
for (String className : packageToClasses.get(packageName)) {
- if (!classToSize.containsKey(className)) {
- System.err.println("*** NO SIZE FOUND FOR CLASS " + className
- + " *****");
- } else {
+ if (classToSize.containsKey(className)) {
int curSize = classToSize.get(className);
- cumSizeFromPackages += curSize;
int newSize = curSize + packageToSize.get(packageName);
packageToSize.put(packageName, newSize);
}
@@ -79,16 +84,16 @@
}
}
- public static void computePartialPackageSizes() {
- cumPartialSizeFromPackages = 0;
+ private static void computePartialPackageSizes(
+ Map<String, Float> packageToPartialSize,
+ Map<String, Float> classToPartialSize) {
+ float cumPartialSizeFromPackages = 0f;
+
packageToPartialSize.clear();
for (String packageName : packageToClasses.keySet()) {
packageToPartialSize.put(packageName, 0f);
for (String className : packageToClasses.get(packageName)) {
- if (!classToPartialSize.containsKey(className)) {
- System.err.println("*** NO PARTIAL SIZE FOUND FOR CLASS " + className
- + " *****");
- } else {
+ if (classToPartialSize.containsKey(className)) {
float curSize = classToPartialSize.get(className);
cumPartialSizeFromPackages += curSize;
float newSize = curSize + packageToPartialSize.get(packageName);
@@ -97,5 +102,4 @@
}
}
}
-
}
diff --git a/tools/soyc-vis/src/com/google/gwt/soyc/MakeTopLevelHtmlForPerm.java b/tools/soyc-vis/src/com/google/gwt/soyc/MakeTopLevelHtmlForPerm.java
index 48e0473..c4d747a 100644
--- a/tools/soyc-vis/src/com/google/gwt/soyc/MakeTopLevelHtmlForPerm.java
+++ b/tools/soyc-vis/src/com/google/gwt/soyc/MakeTopLevelHtmlForPerm.java
@@ -16,13 +16,17 @@
package com.google.gwt.soyc;
+import com.google.gwt.dev.util.Util;
+
import java.io.File;
import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -37,7 +41,18 @@
* A utility to make the top level HTTML file for one permutation.
*/
public class MakeTopLevelHtmlForPerm {
+ /**
+ * By a convention shared with the compiler, the initial download is fragment
+ * number 0.
+ */
+ private static final int FRAGMENT_NUMBER_INITIAL_DOWNLOAD = 0;
+ /**
+ * Just within this file, the convention is that the total program is fragment
+ * number -1.
+ */
+ private static final int FRAGMENT_NUMBER_TOTAL_PROGRAM = -1;
+
public static void copyFileOrDirectory(File srcPath, File dstPath,
String classPath, String inputFileName, boolean isDirectory)
throws IOException {
@@ -116,26 +131,25 @@
return escaped;
}
- public static void makeCodeTypeClassesHtmls(
- HashMap<String, CodeCollection> nameToCodeColl) throws IOException {
+ public static void makeCodeTypeClassesHtmls(SizeBreakdown breakdown)
+ throws IOException {
+ HashMap<String, CodeCollection> nameToCodeColl = breakdown.nameToCodeColl;
for (String codeType : nameToCodeColl.keySet()) {
// construct file name
- String outFileName = codeType + "Classes.html";
+ String outFileName = breakdown.getId() + "_" + codeType + "Classes.html";
float maxSize = 0f;
TreeMap<Float, String> sortedClasses = new TreeMap<Float, String>(
Collections.reverseOrder());
+
for (String className : nameToCodeColl.get(codeType).classes) {
- if (GlobalInformation.classToPartialSize.containsKey(className)) {
+ if (breakdown.classToPartialSize.containsKey(className)) {
float curSize = 0f;
- if (!GlobalInformation.classToPartialSize.containsKey(className)) {
- System.err.println("*** NO PARTIAL SIZE FOUND FOR CLASS "
- + className + " *****");
- } else {
- curSize = GlobalInformation.classToPartialSize.get(className);
+ if (breakdown.classToPartialSize.containsKey(className)) {
+ curSize = breakdown.classToPartialSize.get(className);
}
if (curSize != 0f) {
@@ -168,10 +182,10 @@
outFile.println("<center>");
outFile.println("<h2>Classes of type \"" + codeType + "\"</h2>");
+ addHeaderWithBreakdownContext(breakdown, outFile);
outFile.println("</center>");
- outFile.println("<hr>");
- outFile.println("<div style=\"width:90%; height:80%; overflow-y:auto; overflow-x:auto; top: 90px; left:70px; position:absolute; background-color:white\"");
+ outFile.println("<div style=\"width:90%; height:80%; overflow-y:auto; overflow-x:auto; top: 120px; left:70px; position:absolute; background-color:white\"");
int yOffset = 0;
for (Float size : sortedClasses.keySet()) {
@@ -212,7 +226,7 @@
}
}
- public static void makeDependenciesHtml(
+ public void makeDependenciesHtml(
Map<String, ArrayList<String>> dependencies) throws IOException {
String origOutFileName = "methodDependencies-";
@@ -245,7 +259,8 @@
outFile.close();
}
- String outFileName = origOutFileName + curPackageName + ".html";
+ String outFileName = origOutFileName + filename(curPackageName)
+ + ".html";
outFile = new PrintWriter(outFileName);
outFile.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"");
@@ -300,12 +315,13 @@
}
}
- public static void makeHTMLShell(
- HashMap<String, CodeCollection> nameToCodeColl,
- TreeMap<String, LiteralsCollection> nameToLitColl) throws IOException {
+ public static void makeBreakdownShell(SizeBreakdown breakdown) throws IOException {
// this will contain the place holder iframes where the actual information
// is going to go.
+ Map<String, CodeCollection> nameToCodeColl = breakdown.nameToCodeColl;
+ Map<String, LiteralsCollection> nameToLitColl = breakdown.nameToLitColl;
+
// copy from the bin directory to the current directory
String classPath = GlobalInformation.settings.resources.get();
if (classPath == null) {
@@ -330,15 +346,13 @@
File outputDir = new File("images");
copyFileOrDirectory(inputDir, outputDir, classPath, inputFileName, true);
- String fileName = "SoycDashboard-index.html";
-
- final PrintWriter outFile = new PrintWriter(fileName);
+ final PrintWriter outFile = new PrintWriter(shellFileName(breakdown));
outFile.println("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">");
outFile.println("<html>");
outFile.println("<head>");
outFile.println("<title>Story of Your Compile - Top Level Dashboard for Permutation</title>");
- outFile.println("<link rel=\"stylesheet\" href=\"roundedcorners.css\">");
+ outFile.println("<link rel=\"stylesheet\" href=\"roundedCorners.css\">");
outFile.println("<style type=\"text/css\">");
outFile.println("body {background-color: #728FCE}");
outFile.println("h2 {background-color: transparent}");
@@ -349,18 +363,7 @@
outFile.println("<body>");
outFile.println("<center>");
outFile.println("<h3>Story of Your Compile Dashboard</h3>");
- outFile.println("<hr>");
- if (GlobalInformation.fragmentToStories.size() > 1) {
- outFile.println("<b>Full code size: <span style=\"color:maroon\">"
- + GlobalInformation.cumSizeAllCode
- + "</span>, Size of Initial Download: <span style=\"color:maroon\">"
- + GlobalInformation.fragmentToPartialSize.get(0) + "</span></b>");
- } else {
- outFile.println("<b>Full code size: <span style=\"color:maroon\">"
- + GlobalInformation.cumSizeAllCode + "</span></b>");
- }
-
- outFile.println("<hr>");
+ addHeaderWithBreakdownContext(breakdown, outFile);
outFile.println("</center>");
outFile.println(" <div style=\"width:50%; float:left; padding-top: 10px;\">");
@@ -380,15 +383,18 @@
outFile.println("<div style=\"width: 200px; float: left; text-align:left; font-size:16px; \">Code Type</div>");
outFile.println(" </div>");
+ String packageBreakdownFileName = makePackageHtml(breakdown);
outFile.println("<div style=\"height:35%; width:48%; margin:0 auto; background-color:white; float:left;\">");
- outFile.println("<iframe src=\"packageBreakdown.html\" width=100% height=100% scrolling=auto></iframe>");
+ outFile.println("<iframe src=\"" + packageBreakdownFileName
+ + "\" width=100% height=100% scrolling=auto></iframe>");
outFile.println(" </div>");
- makePackageHtml("packageBreakdown.html");
+ String codeTypeBreakdownFileName = makeCodeTypeHtml(breakdown,
+ nameToCodeColl);
outFile.println("<div style=\"height:35%; width:48%; margin:0 auto; background-color:white; float:right;\">");
- outFile.println("<iframe src=\"codeTypeBreakdown.html\" width=100% height=100% scrolling=auto></iframe>");
+ outFile.println("<iframe src=\"" + codeTypeBreakdownFileName
+ + "\" width=100% height=100% scrolling=auto></iframe>");
outFile.println(" </div>");
- makeCodeTypeHtml("codeTypeBreakdown.html", nameToCodeColl);
outFile.println(" <div style=\"width:50%; float:left; padding-top: 10px;\">");
outFile.println("<b>Literals breakdown</b>");
@@ -407,141 +413,34 @@
outFile.println("<div style=\"width: 200px; float: left; text-align:left; font-size:16px; \">String Literal Type</div>");
outFile.println(" </div>");
+ String literalsBreakdownFileName = makeLiteralsHtml(breakdown,
+ nameToLitColl);
outFile.println("<div style=\"height:35%; width:48%; margin:0 auto; background-color:white; float:left;\">");
- outFile.println("<iframe src=\"literalsBreakdown.html\" width=100% height=100% scrolling=auto></iframe>");
+ outFile.println("<iframe src=\"" + literalsBreakdownFileName
+ + "\" width=100% height=100% scrolling=auto></iframe>");
outFile.println("</div>");
- makeLiteralsHtml("literalsBreakdown.html", nameToLitColl);
+ String stringLiteralsBreakdownFileName = makeStringLiteralsHtml(breakdown,
+ nameToLitColl);
outFile.println("<div style=\"height:35%; width:48%; margin:0 auto; background-color:white; float:right;\">");
- outFile.println("<iframe src=\"stringLiteralsBreakdown.html\" width=100% height=100% scrolling=auto></iframe>");
+ outFile.println("<iframe src=\"" + stringLiteralsBreakdownFileName
+ + "\" width=100% height=100% scrolling=auto></iframe>");
outFile.println(" </div>");
- makeStringLiteralsHtml("stringLiteralsBreakdown.html", nameToLitColl);
-
- if (GlobalInformation.fragmentToStories.size() > 1) {
- outFile.println(" <div style=\"width:50%; float:left; padding-top: 10px;\">");
- outFile.println("<b>Breakdown of key runAsync fragments</b>");
- outFile.println(" </div>");
-
- outFile.println(" <div style=\"width:100%; float:left; padding-top: 10px;\">");
- outFile.println("<div style=\"width: 110px; float: left; font-size:16px;\">Size</div>");
- outFile.println("<div style=\"width: 200px; float: left; text-align:left; font-size:16px; \">Fragment</div>");
- outFile.println(" </div>");
-
- outFile.println("<br style=\"clear:both\">");
- makeFragmentsHtml(outFile);
- }
outFile.println(" </body>");
outFile.println("</html>");
outFile.close();
}
- public static void makeLiteralsClassesHtmls(
- TreeMap<String, LiteralsCollection> nameToLitColl) throws IOException {
+ public static void makeLiteralsClassesTableHtmls(SizeBreakdown breakdown)
+ throws IOException {
+ Map<String, LiteralsCollection> nameToLitColl = breakdown.nameToLitColl;
for (String literalType : nameToLitColl.keySet()) {
String outFileName = literalType + "Lits.html";
- final PrintWriter outFile = new PrintWriter(outFileName);
-
- outFile.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"");
- outFile.println("\"http://www.w3.org/TR/html4/strict.dtd\">");
- outFile.println("<html>");
- outFile.println("<head>");
- outFile.println("<meta http-equiv=\"content-type\" content=\"text/html;charset=ISO-8859-1\">");
- outFile.println("<title>Literals of type \"" + literalType + "\"</title>");
- outFile.println("</head>");
-
- outFile.println("<style type=\"text/css\">");
- outFile.println("body {background-color: #728FCE}");
- outFile.println("h2 {background-color: transparent}");
- outFile.println("p {background-color: fuchsia}");
- outFile.println(".tablediv {");
- outFile.println("display: table;");
- outFile.println("width:100%;");
- outFile.println("background-color:#eee;");
- outFile.println("border:1px solid #666666;");
- outFile.println("border-spacing:5px;/*cellspacing:poor IE support for this*/");
- outFile.println("border-collapse:separate;");
- outFile.println("}");
- outFile.println(".celldiv {");
- outFile.println("float:left;/*fix for buggy browsers*/");
- outFile.println("display: table-cell;");
- outFile.println("width:50%;");
- outFile.println("font-size: 14px;");
- outFile.println("background-color:white;");
- outFile.println("}");
- outFile.println(".rowdiv {");
- outFile.println("display: table-row;");
- outFile.println("}");
- outFile.println("</style>");
-
- outFile.println("<body>");
- outFile.println("<center>");
- outFile.println("<h2>Literals of type \"" + literalType + "\"</h2>");
- outFile.println("</center>");
- outFile.println("<hr>");
-
- outFile.println("<div style=\"width:90%; height:80%; overflow-y:auto; overflow-x:auto; top: 30px; left:60px; position:relative; background-color:white\"");
- outFile.println("<div class=\"tablediv\">");
- for (String literal : nameToLitColl.get(literalType).literalToLocations.keySet()) {
-
- if (literal.trim().compareTo("") == 0) {
- literal = "[whitespace only string]";
- }
-
- String newLiteral = "";
- if (literal.length() > 100) {
- int i;
- for (i = 100; i < literal.length(); i = i + 100) {
- String part1 = literal.substring(i - 100, i);
- newLiteral = newLiteral + part1 + " ";
- }
- if (i - 100 > 0) {
- newLiteral = newLiteral + literal.substring(i - 100);
- }
- } else {
- newLiteral = literal;
- }
-
- String escliteral = escapeXml(newLiteral);
- outFile.println("<div class=\"rowdiv\">");
- outFile.println("<div class=\"celldiv\">" + escliteral + "</div>");
-
- for (String location : nameToLitColl.get(literalType).literalToLocations.get(literal)) {
-
- String newLocation = "";
- if (location.length() > 100) {
- int i;
- for (i = 100; i < location.length(); i = i + 100) {
- String part1 = location.substring(i - 100, i);
- newLocation = newLocation + part1 + " ";
- }
- if (i - 100 > 0) {
- newLocation = newLocation + location.substring(i - 100);
- }
- } else {
- newLocation = location;
- }
-
- outFile.println("<div class=\"celldiv\">" + newLocation + "</div>");
- }
- outFile.println("</div>");
- }
- outFile.println("</div>");
- outFile.println("</body>");
- outFile.println("</html>");
- outFile.close();
- }
- }
-
- public static void makeLiteralsClassesTableHtmls(
- TreeMap<String, LiteralsCollection> nameToLitColl) throws IOException {
-
- for (String literalType : nameToLitColl.keySet()) {
-
- String outFileName = literalType + "Lits.html";
- final PrintWriter outFile = new PrintWriter(outFileName);
+ final PrintWriter outFile = new PrintWriter(breakdown.getId() + "_"
+ + outFileName);
outFile.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"");
outFile.println("\"http://www.w3.org/TR/html4/strict.dtd\">");
@@ -560,8 +459,8 @@
outFile.println("<body>");
outFile.println("<center>");
outFile.println("<h2>Literals of type \"" + literalType + "\"</h2>");
+ addHeaderWithBreakdownContext(breakdown, outFile);
outFile.println("</center>");
- outFile.println("<hr>");
outFile.println("<center>");
outFile.println("<table border=\"1\" width=\"80%\" style=\"font-size: 11pt;\" bgcolor=\"white\">");
@@ -640,11 +539,13 @@
}
}
- public static void makePackageClassesHtmls() throws IOException {
-
+ /**
+ * Make size breakdowns for each package for one code collection.
+ */
+ public void makePackageClassesHtmls(SizeBreakdown breakdown)
+ throws IOException {
for (String packageName : GlobalInformation.packageToClasses.keySet()) {
- String outFileName = packageName + "Classes.html";
TreeMap<Float, String> sortedClasses = new TreeMap<Float, String>(
Collections.reverseOrder());
float maxSize = 0f;
@@ -654,11 +555,10 @@
for (String className : GlobalInformation.packageToClasses.get(packageName)) {
float curSize = 0f;
- if (!GlobalInformation.classToPartialSize.containsKey(className)) {
- System.err.println("*** NO PARTIAL SIZE FOUND FOR CLASS " + className
- + " *****");
+ if (!breakdown.classToPartialSize.containsKey(className)) {
+ // This class not present in this code collection
} else {
- curSize = GlobalInformation.classToPartialSize.get(className);
+ curSize = breakdown.classToPartialSize.get(className);
}
int depCount = 0;
@@ -678,7 +578,7 @@
}
}
- final PrintWriter outFile = new PrintWriter(outFileName);
+ PrintWriter outFile = new PrintWriter(classesInPackageFileName(breakdown, packageName));
outFile.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"");
outFile.println("\"http://www.w3.org/TR/html4/strict.dtd\">");
@@ -693,10 +593,10 @@
outFile.println("<center>");
outFile.println("<h2>Classes in package \"" + packageName + "\"</h2>");
+ addHeaderWithBreakdownContext(breakdown, outFile);
outFile.println("</center>");
- outFile.println("<hr>");
- outFile.println("<div style=\"width:90%; height:80%; overflow-y:auto; overflow-x:auto; top: 90px; left:70px; position:absolute; background-color:white\"");
+ outFile.println("<div style=\"width:90%; height:80%; overflow-y:auto; overflow-x:auto; top: 120px; left:70px; position:absolute; background-color:white\"");
int yOffset = 0;
for (Float size : sortedClasses.keySet()) {
@@ -754,7 +654,7 @@
+ "px; left:5px;\">%.1f</div>\n", size);
if (GlobalInformation.displayDependencies == true) {
outFile.println("<div class=\"barlabel\" style=\"top:" + yOffsetText
- + "px; left:70px;\"><a href=\"methodDependencies-" + packageName
+ + "px; left:70px;\"><a href=\"methodDependencies-" + filename(packageName)
+ ".html#" + className + "\">" + className + "</a></div>");
} else {
outFile.println("<div class=\"barlabel\" style=\"top:" + yOffsetText
@@ -780,9 +680,10 @@
* Makes html file for fragment classes. TODO(kprobst): update this once we
* have SOYC updated to supply enough information
*
- * @throws IOException
+ * TODO(spoon) instead of this listing, make a size breakdown for each
+ * exclusive fragment
*/
- public static void makeSplitPointClassesHtmls() throws IOException {
+ public void makeSplitPointClassesHtmls() throws IOException {
// for the initial fragment and the fragments in the load order, we can
// print this immediately
@@ -791,13 +692,18 @@
TreeSet<String> sortedClassesAndMethodsAllOtherFragments = new TreeSet<String>();
for (Integer fragmentName : GlobalInformation.fragmentToStories.keySet()) {
+ if (fragmentName == FRAGMENT_NUMBER_INITIAL_DOWNLOAD) {
+ /*
+ * For the initial download, a size breakdown is availale to replace the
+ * split point class listing
+ */
+ continue;
+ }
- if ((fragmentName != 0)
- && (!GlobalInformation.splitPointToLocation.containsKey(fragmentName))) {
-
+ if (!GlobalInformation.splitPointToLocation.containsKey(fragmentName)) {
// get the stories from ALL the fragments
for (String storyName : GlobalInformation.fragmentToStories.get(fragmentName)) {
- if ((!GlobalInformation.nameToLitColl.get("string").storyToLocations.containsKey(storyName))
+ if ((!GlobalInformation.totalCodeBreakdown.nameToLitColl.get("string").storyToLocations.containsKey(storyName))
&& (GlobalInformation.storiesToCorrClassesAndMethods.containsKey(storyName))) {
for (String className : GlobalInformation.storiesToCorrClassesAndMethods.get(storyName)) {
sortedClassesAndMethodsAllOtherFragments.add(className);
@@ -807,14 +713,14 @@
} else {
String curSplitPointLocation;
- if (fragmentName == 0) {
+ if (fragmentName == FRAGMENT_NUMBER_INITIAL_DOWNLOAD) {
curSplitPointLocation = "initialDownload";
} else {
curSplitPointLocation = GlobalInformation.splitPointToLocation.get(fragmentName);
}
- String outFileName = "splitPoint" + curSplitPointLocation
- + "Classes.html";
+ String outFileName = "splitPoint-" + filename(curSplitPointLocation)
+ + "-Classes.html";
final PrintWriter outFile = new PrintWriter(outFileName);
@@ -864,7 +770,7 @@
TreeSet<String> sortedClassesAndMethods = new TreeSet<String>();
for (String storyName : GlobalInformation.fragmentToStories.get(fragmentName)) {
- if ((!GlobalInformation.nameToLitColl.get("string").storyToLocations.containsKey(storyName))
+ if ((!GlobalInformation.totalCodeBreakdown.nameToLitColl.get("string").storyToLocations.containsKey(storyName))
&& (GlobalInformation.storiesToCorrClassesAndMethods.containsKey(storyName))) {
for (String className : GlobalInformation.storiesToCorrClassesAndMethods.get(storyName)) {
sortedClassesAndMethods.add(className);
@@ -884,7 +790,7 @@
noParamMethod = noParamMethod.replaceAll("\\(.*", "");
outFile.println("<div class=\"rowdiv\"><a href=\"methodDependencies-"
- + packageName
+ + filename(packageName)
+ ".html#"
+ noParamMethod
+ "\">"
@@ -901,193 +807,16 @@
outFile.close();
}
}
-
- // finally, make the file for all the other fragments
- String outFileName = "splitPointAllOtherFragmentsClasses.html";
-
- final PrintWriter outFile = new PrintWriter(outFileName);
-
- outFile.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"");
- outFile.println("\"http://www.w3.org/TR/html4/strict.dtd\">");
- outFile.println("<html>");
- outFile.println("<head>");
- outFile.println("<meta http-equiv=\"content-type\" content=\"text/html;charset=ISO-8859-1\">");
- outFile.println("<title>Classes and methods in exclusives fragment for runAsync split point \"allOtherFragments\" </title>");
- outFile.println("</head>");
-
- outFile.println("<style type=\"text/css\">");
- outFile.println("body {background-color: #728FCE}");
- outFile.println("h2 {background-color: transparent}");
- outFile.println("p {background-color: fuchsia}");
- outFile.println(".tablediv {");
- outFile.println("display: table;");
- outFile.println("width:100%;");
- outFile.println("background-color:#eee;");
- outFile.println("border:1px solid #666666;");
- outFile.println("border-spacing:5px;/*cellspacing:poor IE support for this*/");
- outFile.println("border-collapse:separate;");
- outFile.println("}");
- outFile.println(".celldiv {");
- outFile.println("float:left;/*fix for buggy browsers*/");
- outFile.println("display: table-cell;");
- outFile.println("width:49.5%;");
- outFile.println("font-size: 14px;");
- outFile.println("background-color:white;");
- outFile.println("}");
- outFile.println(".rowdiv {");
- outFile.println("display: table-row;");
- outFile.println("width:100%;");
- outFile.println("}");
- outFile.println("</style>");
-
- outFile.println("<body>");
- outFile.println("<center>");
- outFile.println("<h2>Classes and methods in exclusives fragment for runAsync split point \"allOtherFragments\"</h2>");
- outFile.println("</center>");
- outFile.println("<hr>");
-
- outFile.println("<div style=\"width:90%; height:80%; overflow-y:auto; overflow-x:auto; top: 30px; left:60px; position:relative; background-color:white\"");
- outFile.println("<div class=\"tablediv\">");
-
- for (String classOrMethod : sortedClassesAndMethodsAllOtherFragments) {
-
- // if it's a method
- if ((GlobalInformation.displayDependencies == true)
- && (classOrMethod.contains("(")) && (classOrMethod.contains(")"))) {
- // get the package
- String packageName = classOrMethod;
- packageName = packageName.replaceAll("\\.\\p{Upper}.*", "");
-
- String noParamMethod = classOrMethod;
- noParamMethod = noParamMethod.replaceAll("\\(.*", "");
-
- outFile.println("<div class=\"rowdiv\"><a href=\"methodDependencies-"
- + packageName + ".html#" + noParamMethod + "\">" + classOrMethod
- + "</a></div>");
- } else {
- outFile.println("<div class=\"rowdiv\">" + classOrMethod + "</div>");
- }
- }
-
- outFile.println("</div>");
- outFile.println("</body>");
- outFile.println("</html>");
- outFile.close();
}
- public static void makeStringLiteralsClassesHtmls(
- TreeMap<String, LiteralsCollection> nameToLitColl) throws IOException {
+ public static void makeStringLiteralsClassesTableHtmls(SizeBreakdown breakdown)
+ throws IOException {
+ Map<String, LiteralsCollection> nameToLitColl = breakdown.nameToLitColl;
for (String literalType : nameToLitColl.get("string").stringTypeToSize.keySet()) {
-
String outFileName = literalType + "Strings.html";
-
- final PrintWriter outFile = new PrintWriter(outFileName);
-
- outFile.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"");
- outFile.println("\"http://www.w3.org/TR/html4/strict.dtd\">");
- outFile.println("<html>");
- outFile.println("<head>");
- outFile.println("<meta http-equiv=\"content-type\" content=\"text/html;charset=ISO-8859-1\">");
- outFile.println("<title>Literals of type \"" + literalType + "\"</title>");
- outFile.println("</head>");
-
- outFile.println("<style type=\"text/css\">");
- outFile.println("body {background-color: #728FCE}");
- outFile.println("h2 {background-color: transparent}");
- outFile.println("p {background-color: fuchsia}");
- outFile.println(".tablediv {");
- outFile.println("display: table;");
- outFile.println("width:100%;");
- outFile.println("background-color:#eee;");
- outFile.println("border:1px solid #666666;");
- outFile.println("border-spacing:5px;/*cellspacing:poor IE support for this*/");
- outFile.println("border-collapse:separate;");
- outFile.println("}");
- outFile.println(".celldiv {");
- outFile.println("float:left;/*fix for buggy browsers*/");
- outFile.println("display: table-cell;");
- outFile.println("width:49.5%;");
- outFile.println("font-size: 14px;");
- outFile.println("background-color:white;");
- outFile.println("}");
- outFile.println(".rowdiv {");
- outFile.println("display: table-row;");
- outFile.println("width:100%;");
- outFile.println("}");
- outFile.println("</style>");
-
- outFile.println("<body>");
- outFile.println("<center>");
- outFile.println("<h2>Literals of type \"" + literalType + "\"</h2>");
- outFile.println("</center>");
- outFile.println("<hr>");
-
- outFile.println("<div style=\"width:90%; height:80%; overflow-y:auto; overflow-x:auto; top: 30px; left:60px; position:relative; background-color:white\"");
- outFile.println("<div class=\"tablediv\">");
-
- for (String literal : nameToLitColl.get("string").stringLiteralToType.keySet()) {
-
- if (nameToLitColl.get("string").stringLiteralToType.get(literal).compareTo(
- literalType) == 0) {
-
- if (literal.trim().compareTo("") == 0) {
- literal = "[whitespace only string]";
- }
-
- String newLiteral = "";
- if (literal.length() > 100) {
- int i;
- for (i = 100; i < literal.length(); i = i + 100) {
- String part1 = literal.substring(i - 100, i);
- newLiteral = newLiteral + part1 + " ";
- }
- if (i - 100 > 0) {
- newLiteral = newLiteral + literal.substring(i - 100);
- }
- } else {
- newLiteral = literal;
- }
-
- String escliteral = escapeXml(newLiteral);
- outFile.println("<div class=\"rowdiv\">");
- outFile.println("<div class=\"celldiv\">" + escliteral + "</div>");
-
- for (String location : nameToLitColl.get("string").literalToLocations.get(literal)) {
-
- String newLocation = "";
- if (location.length() > 100) {
- int i;
- for (i = 100; i < location.length(); i = i + 100) {
- String part1 = location.substring(i - 100, i);
- newLocation = newLocation + part1 + " ";
- }
- if (i - 100 > 0) {
- newLocation = newLocation + location.substring(i - 100);
- }
- } else {
- newLocation = location;
- }
-
- outFile.println("<div class=\"celldiv\">" + newLocation + "</div>");
- }
- outFile.println("</div>");
- }
- }
- outFile.println("</div>");
- outFile.println("</body>");
- outFile.println("</html>");
- outFile.close();
- }
- }
-
- public static void makeStringLiteralsClassesTableHtmls(
- TreeMap<String, LiteralsCollection> nameToLitColl) throws IOException {
-
- for (String literalType : nameToLitColl.get("string").stringTypeToSize.keySet()) {
-
- String outFileName = literalType + "Strings.html";
- final PrintWriter outFile = new PrintWriter(outFileName);
+ final PrintWriter outFile = new PrintWriter(breakdown.getId() + "_"
+ + outFileName);
outFile.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"");
outFile.println("\"http://www.w3.org/TR/html4/strict.dtd\">");
@@ -1106,8 +835,8 @@
outFile.println("<body>");
outFile.println("<center>");
outFile.println("<h2>Literals of type \"" + literalType + "\"</h2>");
+ addHeaderWithBreakdownContext(breakdown, outFile);
outFile.println("</center>");
- outFile.println("<hr>");
outFile.println("<center>");
outFile.println("<table border=\"1\" width=\"80%\" style=\"font-size: 11pt;\" bgcolor=\"white\">");
@@ -1190,9 +919,32 @@
}
}
- private static void makeCodeTypeHtml(String outFileName,
- HashMap<String, CodeCollection> nameToCodeColl) throws IOException {
+ /**
+ * Adds a header line indicating which breakdown is being analyzed.
+ */
+ private static void addHeaderWithBreakdownContext(SizeBreakdown breakdown,
+ final PrintWriter outFile) {
+ outFile.println("<hr>");
+ outFile.println("<b>(Analyzing code subset: " + breakdown.getDescription()
+ + ")</b>");
+ outFile.println("<hr>");
+ }
+ /**
+ * Convert a potentially long string into a short file name. The current
+ * implementation simply hashes the long name.
+ */
+ private static String filename(String longFileName) {
+ try {
+ return Util.computeStrongName(longFileName.getBytes(Util.DEFAULT_ENCODING));
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static String makeCodeTypeHtml(SizeBreakdown breakdown,
+ Map<String, CodeCollection> nameToCodeColl) throws IOException {
+ String outFileName = breakdown.getId() + "_codeTypeBreakdown.html";
float maxSize = 0f;
float sumSize = 0f;
TreeMap<Float, String> sortedCodeTypes = new TreeMap<Float, String>(
@@ -1201,7 +953,7 @@
// TODO(kprobst): turn this into a multimap?
// com.google.common.collect.TreeMultimap
for (String codeType : nameToCodeColl.keySet()) {
- float curSize = nameToCodeColl.get(codeType).getCumPartialSize();
+ float curSize = nameToCodeColl.get(codeType).getCumPartialSize(breakdown);
sumSize += curSize;
if (curSize != 0f) {
@@ -1227,7 +979,8 @@
for (Float size : sortedCodeTypes.keySet()) {
String codeType = sortedCodeTypes.get(size);
- String drillDownFileName = codeType + "Classes.html";
+ String drillDownFileName = breakdown.getId() + "_" + codeType
+ + "Classes.html";
float ratio = (size / maxSize) * 79;
float perc = (size / sumSize) * 100;
@@ -1263,29 +1016,75 @@
outFile.println("</body>");
outFile.println("</html>");
outFile.close();
+
+ return outFileName;
}
- private static void makeFragmentsHtml(PrintWriter outFile) throws IOException {
- int numSplitPoints = GlobalInformation.splitPointToLocation.size();
+ public static void makeTopLevelShell() throws IOException {
+ PrintWriter outFile = new PrintWriter("SoycDashboard-index.html");
+
+ outFile.println("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">");
+ outFile.println("<html>");
+ outFile.println("<head>");
+ outFile.println("<title>Story of Your Compile - Top Level Dashboard for Permutation</title>");
+ outFile.println("<link rel=\"stylesheet\" href=\"roundedCorners.css\">");
+ outFile.println("<style type=\"text/css\">");
+ outFile.println("body {background-color: #728FCE}");
+ outFile.println("h2 {background-color: transparent}");
+ outFile.println("p {background-color: fuchsia}");
+ outFile.println("</style>");
+ outFile.println("</head>");
- int outerHeight = 25 * (numSplitPoints + 1);
- outFile.println("<div style=\"width:100%; margin:20px 0 20px 0; background-color:white;position:relative;height:"
- + outerHeight + "\">");
- float maxSize = 0;
- for (int i = 0; i <= numSplitPoints; i++) {
- maxSize += GlobalInformation.fragmentToPartialSize.get(i);
+ outFile.println("<body>");
+ outFile.println("<center>");
+ outFile.println("<h3>Story of Your Compile Dashboard</h3>");
+ outFile.println("<hr>");
+ if (GlobalInformation.fragmentToStories.size() > 1) {
+ outFile.println("<b>Initial download size: <span style=\"color:maroon\">"
+ + GlobalInformation.initialCodeBreakdown.sizeAllCode
+ + "</span></span></b>");
+ } else {
+ outFile.println("<b>Full code size: <span style=\"color:maroon\">"
+ + GlobalInformation.totalCodeBreakdown.sizeAllCode
+ + "</span></span></b>");
}
- int yOffset = 0;
- for (int i = 0; i <= numSplitPoints; i++) {
- String splitPointName = i == 0 ? "initialDownload"
- : GlobalInformation.splitPointToLocation.get(i);
- String drillDownFileName = "splitPoint" + splitPointName + "Classes.html";
- String splitPointDescription = i == 0 ? "Initial download"
- : ("Code exclusive to " + splitPointName);
+ outFile.println("<hr>");
+
+ outFile.println("Available code subsets to analyze");
- float size = GlobalInformation.fragmentToPartialSize.get(i);
+ int numSplitPoints = GlobalInformation.splitPointToLocation.size();
+
+ int outerHeight = 25 * (numSplitPoints + 2);
+ outFile.println("<div style=\"width:100%; margin:20px 0 20px 0; background-color:white;position:relative;height:"
+ + outerHeight + "\">");
+ float maxSize = GlobalInformation.totalCodeBreakdown.sizeAllCode;
+
+ int yOffset = 0;
+ for (int i = FRAGMENT_NUMBER_TOTAL_PROGRAM; i <= numSplitPoints; i++) {
+ String drillDownFileName, splitPointDescription;
+ if (i == FRAGMENT_NUMBER_TOTAL_PROGRAM) {
+ drillDownFileName = shellFileName(GlobalInformation.totalCodeBreakdown);
+ splitPointDescription = "Total program";
+ } else {
+ String splitPointName = i == FRAGMENT_NUMBER_INITIAL_DOWNLOAD ? "initialDownload"
+ : GlobalInformation.splitPointToLocation.get(i);
+ if (i == FRAGMENT_NUMBER_INITIAL_DOWNLOAD) {
+ drillDownFileName = shellFileName(GlobalInformation.initialCodeBreakdown);
+ } else {
+ drillDownFileName = "splitPoint-" + filename(splitPointName) + "-Classes.html";
+ }
+ splitPointDescription = i == FRAGMENT_NUMBER_INITIAL_DOWNLOAD ? "Initial download"
+ : ("Code exclusive to " + splitPointName);
+ }
+
+ float size;
+ if (i >= 0) {
+ size = GlobalInformation.fragmentToPartialSize.get(i);
+ } else {
+ size = GlobalInformation.totalCodeBreakdown.sizeAllCode;
+ }
float ratio = (size / maxSize) * 79;
if (ratio < 3) {
ratio = 3;
@@ -1313,11 +1112,13 @@
yOffset = yOffset + 25;
}
outFile.println("</div>");
+ outFile.println("</body></html>");
+ outFile.close();
}
- private static void makeLiteralsHtml(String outFileName,
- TreeMap<String, LiteralsCollection> nameToLitColl) throws IOException {
-
+ private static String makeLiteralsHtml(SizeBreakdown breakdown,
+ Map<String, LiteralsCollection> nameToLitColl) throws IOException {
+ String outFileName = breakdown.getId() + "_literalsBreakdown.html";
float maxSize = 0f;
float sumSize = 0f;
TreeMap<Float, String> sortedLitTypes = new TreeMap<Float, String>(
@@ -1351,7 +1152,8 @@
for (Float size : sortedLitTypes.keySet()) {
String literal = sortedLitTypes.get(size);
- String drillDownFileName = literal + "Lits.html";
+ String drillDownFileName = breakdown.getId() + "_" + literal
+ + "Lits.html";
float ratio = (size / maxSize) * 79;
float perc = (size / sumSize) * 100;
@@ -1387,20 +1189,23 @@
outFile.println("</body>");
outFile.println("</html>");
outFile.close();
+
+ return outFileName;
}
- private static void makePackageHtml(String outFileName) throws IOException {
-
+ private static String makePackageHtml(SizeBreakdown breakdown)
+ throws FileNotFoundException {
+ String outFileName = breakdown.getId() + "_" + "packageBreakdown.html";
+ Map<String, Float> packageToPartialSize = breakdown.packageToPartialSize;
TreeMap<Float, String> sortedPackages = new TreeMap<Float, String>(
Collections.reverseOrder());
float maxSize = 0f;
float sumSize = 0f;
- for (String packageName : GlobalInformation.packageToPartialSize.keySet()) {
- sortedPackages.put(
- GlobalInformation.packageToPartialSize.get(packageName), packageName);
- sumSize += GlobalInformation.packageToPartialSize.get(packageName);
- if (GlobalInformation.packageToPartialSize.get(packageName) > maxSize) {
- maxSize = GlobalInformation.packageToPartialSize.get(packageName);
+ for (String packageName : packageToPartialSize.keySet()) {
+ sortedPackages.put(packageToPartialSize.get(packageName), packageName);
+ sumSize += packageToPartialSize.get(packageName);
+ if (packageToPartialSize.get(packageName) > maxSize) {
+ maxSize = packageToPartialSize.get(packageName);
}
}
@@ -1418,9 +1223,8 @@
int yOffset = 0;
for (Float size : sortedPackages.keySet()) {
-
String packageName = sortedPackages.get(size);
- String drillDownFileName = packageName + "Classes.html";
+ String drillDownFileName = classesInPackageFileName(breakdown, packageName);
float ratio = (size / maxSize) * 79;
@@ -1457,11 +1261,19 @@
outFile.println("</body>");
outFile.println("</html>");
outFile.close();
+
+ return outFileName;
}
- private static void makeStringLiteralsHtml(String outFileName,
- TreeMap<String, LiteralsCollection> nameToLitColl) throws IOException {
+ private static String classesInPackageFileName(SizeBreakdown breakdown,
+ String packageName) {
+ return breakdown.getId() + "_" + packageName
+ + "_Classes.html";
+ }
+ private static String makeStringLiteralsHtml(SizeBreakdown breakdown,
+ Map<String, LiteralsCollection> nameToLitColl) throws IOException {
+ String outFileName = breakdown.getId() + "_stringLiteralsBreakdown.html";
final PrintWriter outFile = new PrintWriter(outFileName);
outFile.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"");
@@ -1497,7 +1309,8 @@
for (Float size : sortedStLitTypes.keySet()) {
String stringLiteral = sortedStLitTypes.get(size);
- String drillDownFileName = stringLiteral + "Strings.html";
+ String drillDownFileName = breakdown.getId() + "_" + stringLiteral
+ + "Strings.html";
float ratio = (size / maxSize) * 79;
float perc = (size / sumSize) * 100;
@@ -1537,5 +1350,11 @@
outFile.println("</body>");
outFile.println("</html>");
outFile.close();
+
+ return outFileName;
+ }
+
+ private static String shellFileName(SizeBreakdown breakdown) {
+ return breakdown.getId() + "-overallBreakdown.html";
}
}
diff --git a/tools/soyc-vis/src/com/google/gwt/soyc/SizeBreakdown.java b/tools/soyc-vis/src/com/google/gwt/soyc/SizeBreakdown.java
new file mode 100644
index 0000000..1d0136a
--- /dev/null
+++ b/tools/soyc-vis/src/com/google/gwt/soyc/SizeBreakdown.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2009 Google Inc.
+ *
+ * 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.
+ */
+package com.google.gwt.soyc;
+
+import com.google.gwt.dev.util.collect.HashSet;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+/**
+ * A size breakdown of one code collection.
+ */
+public class SizeBreakdown {
+ private static void initializeLiteralsCollection(
+ Map<String, LiteralsCollection> nameToLitColl) {
+ nameToLitColl.put("long", new LiteralsCollection("long"));
+ nameToLitColl.put("null", new LiteralsCollection("null"));
+ nameToLitColl.put("class", new LiteralsCollection("class"));
+ nameToLitColl.put("int", new LiteralsCollection("int"));
+ nameToLitColl.put("string", new LiteralsCollection("string"));
+ nameToLitColl.put("number", new LiteralsCollection("number"));
+ nameToLitColl.put("boolean", new LiteralsCollection("boolean"));
+ nameToLitColl.put("double", new LiteralsCollection("double"));
+ nameToLitColl.put("char", new LiteralsCollection("char"));
+ nameToLitColl.put("undefined", new LiteralsCollection("undefined"));
+ nameToLitColl.put("float", new LiteralsCollection("float"));
+ }
+
+ private static void initializeNameToCodeCollection(
+ HashMap<String, CodeCollection> nameToCodeColl) {
+ nameToCodeColl.put("allOther", new CodeCollection("allOther"));
+ nameToCodeColl.put("widget", new CodeCollection("widget"));
+ nameToCodeColl.put("rpcUser", new CodeCollection("rpcUser"));
+ nameToCodeColl.put("rpcGen", new CodeCollection("rpcGen"));
+ nameToCodeColl.put("rpcGwt", new CodeCollection("rpcGwt"));
+ nameToCodeColl.put("gwtLang", new CodeCollection("long"));
+ nameToCodeColl.put("jre", new CodeCollection("jre"));
+ }
+
+ public Map<String, Float> classToPartialSize = new HashMap<String, Float>();
+ public Map<String, Integer> classToSize = new HashMap<String, Integer>();
+ public Map<String, LiteralsCollection> nameToLitColl = new TreeMap<String, LiteralsCollection>();
+ public int nonAttributedBytes = 0;
+ public Set<String> nonAttributedStories = new HashSet<String>();;
+ public Map<String, Float> packageToPartialSize = new HashMap<String, Float>();
+ public Map<String, Integer> packageToSize = new HashMap<String, Integer>();
+ public HashMap<String, CodeCollection> nameToCodeColl = new HashMap<String, CodeCollection>();
+
+ public int sizeAllCode;
+
+ private final String description;
+ private final String id;
+
+ public SizeBreakdown(String description, String id) {
+ this.description = description;
+ this.id = id;
+
+ initializeLiteralsCollection(nameToLitColl);
+ initializeNameToCodeCollection(nameToCodeColl);
+ }
+
+ /**
+ * A short but human-readable description of this code collection.
+ */
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * An identifier for this code collection suitable for use within file names.
+ */
+ public String getId() {
+ return id;
+ }
+}
diff --git a/tools/soyc-vis/src/com/google/gwt/soyc/SoycDashboard.java b/tools/soyc-vis/src/com/google/gwt/soyc/SoycDashboard.java
index 4a2b57c..7fbf605 100644
--- a/tools/soyc-vis/src/com/google/gwt/soyc/SoycDashboard.java
+++ b/tools/soyc-vis/src/com/google/gwt/soyc/SoycDashboard.java
@@ -26,8 +26,10 @@
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.TreeSet;
@@ -43,6 +45,7 @@
public class SoycDashboard {
public static void main(String[] args) {
+ System.out.println("Generating the Story of Your Compile...");
try {
GlobalInformation.settings = Settings.fromArgumentList(args);
} catch (Settings.ArgumentListException e) {
@@ -57,6 +60,8 @@
GlobalInformation.displayDependencies = (settings.depFileName != null);
GlobalInformation.displaySplitPoints = (settings.splitPointsFileName != null);
+ MakeTopLevelHtmlForPerm makeTopLevelHtmlForPerm = new MakeTopLevelHtmlForPerm();
+
if (GlobalInformation.displayDependencies == true) {
/**
* handle dependencies
@@ -87,7 +92,7 @@
}
try {
- MakeTopLevelHtmlForPerm.makeDependenciesHtml(dependencies);
+ makeTopLevelHtmlForPerm.makeDependenciesHtml(dependencies);
} catch (IOException e) {
throw new RuntimeException("Cannot open file. ", e);
}
@@ -126,40 +131,8 @@
* handle everything else
*/
- // to store literals data
- GlobalInformation.nameToLitColl.put("long", new LiteralsCollection("long"));
- GlobalInformation.nameToLitColl.put("null", new LiteralsCollection("null"));
- GlobalInformation.nameToLitColl.put("class",
- new LiteralsCollection("class"));
- GlobalInformation.nameToLitColl.put("int", new LiteralsCollection("int"));
- GlobalInformation.nameToLitColl.put("string", new LiteralsCollection(
- "string"));
- GlobalInformation.nameToLitColl.put("number", new LiteralsCollection(
- "number"));
- GlobalInformation.nameToLitColl.put("boolean", new LiteralsCollection(
- "boolean"));
- GlobalInformation.nameToLitColl.put("double", new LiteralsCollection(
- "double"));
- GlobalInformation.nameToLitColl.put("char", new LiteralsCollection("char"));
- GlobalInformation.nameToLitColl.put("undefined", new LiteralsCollection(
- "undefined"));
- GlobalInformation.nameToLitColl.put("float",
- new LiteralsCollection("float"));
-
- // to store code data
- GlobalInformation.nameToCodeColl.put("allOther", new CodeCollection(
- "allOther"));
- GlobalInformation.nameToCodeColl.put("widget", new CodeCollection("widget"));
- GlobalInformation.nameToCodeColl.put("rpcUser", new CodeCollection(
- "rpcUser"));
- GlobalInformation.nameToCodeColl.put("rpcGen", new CodeCollection("rpcGen"));
- GlobalInformation.nameToCodeColl.put("rpcGwt", new CodeCollection("rpcGwt"));
- GlobalInformation.nameToCodeColl.put("gwtLang", new CodeCollection("long"));
- GlobalInformation.nameToCodeColl.put("jre", new CodeCollection("jre"));
-
// make the parser handler
- DefaultHandler handler = parseXMLDocument(GlobalInformation.nameToLitColl,
- GlobalInformation.nameToCodeColl);
+ DefaultHandler handler = parseXMLDocument();
// start parsing
SAXParserFactory factoryMain = SAXParserFactory.newInstance();
@@ -183,18 +156,23 @@
}
// add to "All Other Code" if none of the special categories apply
- updateAllOtherCodeType(GlobalInformation.nameToCodeColl);
+ for (SizeBreakdown breakdown : GlobalInformation.allSizeBreakdowns()) {
+ updateAllOtherCodeType(breakdown.nameToCodeColl);
+ }
// now we need to aggregate numbers
GlobalInformation.computePackageSizes();
GlobalInformation.computePartialPackageSizes();
// clean up the RPC categories
- foldInRPCHeuristic(GlobalInformation.nameToCodeColl);
+ for (SizeBreakdown breakdown : GlobalInformation.allSizeBreakdowns()) {
+ foldInRPCHeuristic(breakdown.nameToCodeColl);
+ }
// generate all the html files
- makeHTMLFiles(GlobalInformation.nameToLitColl,
- GlobalInformation.nameToCodeColl);
+ for (SizeBreakdown breakdown : GlobalInformation.allSizeBreakdowns()) {
+ makeHTMLFiles(makeTopLevelHtmlForPerm, breakdown);
+ }
System.out.println("Finished creating reports. To see the dashboard, open SoycDashboard-index.html in your browser.");
}
@@ -247,34 +225,28 @@
}
}
- /*
+ /**
* generates all the HTML files
*/
private static void makeHTMLFiles(
- final TreeMap<String, LiteralsCollection> nameToLitColl,
- final HashMap<String, CodeCollection> nameToCodeColl) {
-
+ MakeTopLevelHtmlForPerm makeTopLevelHtmlForPerm, SizeBreakdown breakdown) {
try {
- MakeTopLevelHtmlForPerm.makePackageClassesHtmls();
- MakeTopLevelHtmlForPerm.makeCodeTypeClassesHtmls(nameToCodeColl);
- MakeTopLevelHtmlForPerm.makeLiteralsClassesTableHtmls(nameToLitColl);
- MakeTopLevelHtmlForPerm.makeStringLiteralsClassesTableHtmls(nameToLitColl);
- MakeTopLevelHtmlForPerm.makeSplitPointClassesHtmls();
-
- // make the shell last so we can display aggregate information here
- MakeTopLevelHtmlForPerm.makeHTMLShell(nameToCodeColl, nameToLitColl);
-
+ makeTopLevelHtmlForPerm.makePackageClassesHtmls(breakdown);
+ MakeTopLevelHtmlForPerm.makeCodeTypeClassesHtmls(breakdown);
+ MakeTopLevelHtmlForPerm.makeLiteralsClassesTableHtmls(breakdown);
+ MakeTopLevelHtmlForPerm.makeStringLiteralsClassesTableHtmls(breakdown);
+ makeTopLevelHtmlForPerm.makeSplitPointClassesHtmls();
+ MakeTopLevelHtmlForPerm.makeBreakdownShell(breakdown);
+ MakeTopLevelHtmlForPerm.makeTopLevelShell();
} catch (IOException e) {
+ // TODO(spoon) pass all internal IOExceptions back to the top, so the
+ // give-up logic is in just one place
throw new RuntimeException("Cannot open file. ", e);
}
}
- private static DefaultHandler parseXMLDocument(
- final TreeMap<String, LiteralsCollection> nameToLitColl,
- final HashMap<String, CodeCollection> nameToCodeColl) {
-
+ private static DefaultHandler parseXMLDocument() {
DefaultHandler handler = new DefaultHandler() {
-
String curClassId;
Integer curFragment;
String curLineNumber;
@@ -284,7 +256,6 @@
String curStoryId;
String curStoryLiteralType;
String curStoryRef;
- boolean fragmentInLoadOrder = false;
boolean specialCodeType = false;
StringBuilder valueBuilder = new StringBuilder();
@@ -312,7 +283,7 @@
if (strippedName.compareTo("storyref") == 0) {
String value = valueBuilder.toString();
- int numBytes = value.getBytes().length;
+ int numBytes = currentStorySize();
if (curStoryRef != null) {
if (!GlobalInformation.fragmentToPartialSize.containsKey(curFragment)) {
GlobalInformation.fragmentToPartialSize.put(curFragment,
@@ -323,12 +294,8 @@
GlobalInformation.fragmentToPartialSize.put(curFragment, newSize);
}
- // now do different things depending on whether this fragment is in
- // the load order or not
- if (fragmentInLoadOrder == false) {
- GlobalInformation.allOtherFragmentsPartialSize += numBytes;
- } else {
- GlobalInformation.cumSizeAllCode += numBytes;
+ for (SizeBreakdown breakdown : breakdownsForCurFragment()) {
+ breakdown.sizeAllCode += numBytes;
}
// add this size to the classes associated with it
@@ -339,66 +306,14 @@
GlobalInformation.numBytesDoubleCounted += numBytes;
}
- float partialSize = (float) numBytes
- / (float) GlobalInformation.storiesToCorrClasses.get(
- curStoryRef).size();
-
- // now do different things depending on whether this fragment is
- // in
- // the load order or not
- if (fragmentInLoadOrder == true) {
- if ((!GlobalInformation.storiesToLitType.containsKey(curStoryRef))
- && (!GlobalInformation.storiesToCorrClasses.containsKey(curStoryRef))) {
- GlobalInformation.nonAttributedStories.add(curStoryRef);
- GlobalInformation.nonAttributedBytes += numBytes;
- }
-
- // go through all the classes for this story
- for (String className : GlobalInformation.storiesToCorrClasses.get(curStoryRef)) {
- // get the corresponding package
-
- String packageName = "";
-
- if (!GlobalInformation.classToPackage.containsKey(className)) {
- // derive the package name from the class
- packageName = className;
- packageName = packageName.replaceAll("\\.[A-Z].*", "");
- GlobalInformation.classToPackage.put(className, packageName);
- } else {
- packageName = GlobalInformation.classToPackage.get(className);
- }
- parseClass(nameToCodeColl, className, packageName);
-
- if (!GlobalInformation.packageToClasses.containsKey(packageName)) {
- TreeSet<String> insertSet = new TreeSet<String>();
- insertSet.add(className);
- GlobalInformation.packageToClasses.put(packageName,
- insertSet);
- } else {
- GlobalInformation.packageToClasses.get(packageName).add(
- className);
- }
-
- if (GlobalInformation.classToSize.containsKey(className)) {
- int newSize = GlobalInformation.classToSize.get(className)
- + numBytes;
- GlobalInformation.classToSize.put(className, newSize);
- } else {
- GlobalInformation.classToSize.put(className, numBytes);
- }
-
- if (GlobalInformation.classToPartialSize.containsKey(className)) {
- float newSize = GlobalInformation.classToPartialSize.get(className)
- + partialSize;
- GlobalInformation.classToPartialSize.put(className, newSize);
- } else {
- GlobalInformation.classToPartialSize.put(className,
- partialSize);
- }
- }
+ for (SizeBreakdown breakdown : breakdownsForCurFragment()) {
+ accountForCurrentStory(breakdown.nameToCodeColl, breakdown);
}
}
- updateLitTypes(nameToLitColl, value, numBytes);
+
+ for (SizeBreakdown breakdown : breakdownsForCurFragment()) {
+ updateLitTypes(breakdown.nameToLitColl, value, numBytes);
+ }
}
}
}
@@ -419,33 +334,101 @@
if (strippedName.compareTo("story") == 0) {
parseStory(attributes);
} else if (strippedName.compareTo("of") == 0) {
- parseOverrides(nameToCodeColl, attributes);
+ for (SizeBreakdown breakdown : breakdownsForCurFragment()) {
+ parseOverrides(breakdown.nameToCodeColl, attributes);
+ }
} else if (strippedName.compareTo("by") == 0) {
- parseCorrelations(nameToCodeColl, attributes);
+ for (SizeBreakdown breakdown : breakdownsForCurFragment()) {
+ parseCorrelations(breakdown.nameToCodeColl, attributes);
+ }
} else if (strippedName.compareTo("origin") == 0) {
- parseOrigins(nameToLitColl, attributes);
+ for (SizeBreakdown breakdown : breakdownsForCurFragment()) {
+ parseOrigins(breakdown.nameToLitColl, attributes);
+ }
} else if (strippedName.compareTo("js") == 0) {
if (attributes.getValue("fragment") != null) {
- // ignore all code that is not in the first load order
-
curFragment = Integer.parseInt(attributes.getValue("fragment"));
- if ((curFragment == 0)
- || (curFragment == (GlobalInformation.numSplitPoints + 1))
- || (curFragment == (GlobalInformation.numSplitPoints + 2))
- || ((curFragment >= 2) && (curFragment <= GlobalInformation.numSplitPoints))) {
- fragmentInLoadOrder = true;
- } else {
- fragmentInLoadOrder = false;
- }
} else {
-
curFragment = -2;
}
} else if (strippedName.compareTo("storyref") == 0) {
- parseJs(nameToLitColl, nameToCodeColl, attributes, curFragment);
+ for (SizeBreakdown breakdown : breakdownsForCurFragment()) {
+ parseJs(breakdown.nameToLitColl, breakdown.nameToCodeColl,
+ attributes, curFragment);
+ }
}
}
+ private void accountForCurrentStory(
+ final HashMap<String, CodeCollection> nameToCodeColl,
+ SizeBreakdown breakdown) {
+ int storySize = currentStorySize();
+ if ((!GlobalInformation.storiesToLitType.containsKey(curStoryRef))
+ && (!GlobalInformation.storiesToCorrClasses.containsKey(curStoryRef))) {
+ breakdown.nonAttributedStories.add(curStoryRef);
+ breakdown.nonAttributedBytes += storySize;
+ }
+
+ // go through all the classes for this story
+ for (String className : GlobalInformation.storiesToCorrClasses.get(curStoryRef)) {
+ // get the corresponding package
+
+ String packageName = "";
+
+ if (!GlobalInformation.classToPackage.containsKey(className)) {
+ // derive the package name from the class
+ packageName = className;
+ packageName = packageName.replaceAll("\\.[A-Z].*", "");
+ GlobalInformation.classToPackage.put(className, packageName);
+ } else {
+ packageName = GlobalInformation.classToPackage.get(className);
+ }
+ parseClass(nameToCodeColl, className, packageName);
+
+ if (!GlobalInformation.packageToClasses.containsKey(packageName)) {
+ TreeSet<String> insertSet = new TreeSet<String>();
+ insertSet.add(className);
+ GlobalInformation.packageToClasses.put(packageName, insertSet);
+ } else {
+ GlobalInformation.packageToClasses.get(packageName).add(className);
+ }
+
+ if (breakdown.classToSize.containsKey(className)) {
+ int newSize = breakdown.classToSize.get(className) + storySize;
+ breakdown.classToSize.put(className, newSize);
+ } else {
+ breakdown.classToSize.put(className, storySize);
+ }
+
+ if (breakdown.classToPartialSize.containsKey(className)) {
+ float newSize = breakdown.classToPartialSize.get(className)
+ + currentStoryPartialSize();
+ breakdown.classToPartialSize.put(className, newSize);
+ } else {
+ breakdown.classToPartialSize.put(className,
+ currentStoryPartialSize());
+ }
+ }
+ }
+
+ private Collection<SizeBreakdown> breakdownsForCurFragment() {
+ List<SizeBreakdown> breakdowns = new ArrayList<SizeBreakdown>();
+ breakdowns.add(GlobalInformation.totalCodeBreakdown);
+ if (curFragment == 0) {
+ breakdowns.add(GlobalInformation.initialCodeBreakdown);
+ }
+ return breakdowns;
+ }
+
+ private float currentStoryPartialSize() {
+ return (float) currentStorySize()
+ / (float) GlobalInformation.storiesToCorrClasses.get(curStoryRef).size();
+ }
+
+ private int currentStorySize() {
+ return valueBuilder.toString().getBytes().length;
+ }
+
/*
* parses the "class" portion of the XML file
*/
@@ -518,8 +501,7 @@
/*
* parses the "JS" portion of the XML file
*/
- private void parseJs(
- final TreeMap<String, LiteralsCollection> nameToLitColl,
+ private void parseJs(final Map<String, LiteralsCollection> nameToLitColl,
final HashMap<String, CodeCollection> nameToCodeColl,
Attributes attributes, Integer curFragment) {
curRelevantLitTypes.clear();
@@ -566,7 +548,7 @@
* parses the "origins" portion of the XML file
*/
private void parseOrigins(
- final TreeMap<String, LiteralsCollection> nameToLitColl,
+ final Map<String, LiteralsCollection> nameToLitColl,
Attributes attributes) {
if ((curStoryLiteralType.compareTo("") != 0)
&& (attributes.getValue("lineNumber") != null)
@@ -623,13 +605,13 @@
curStoryLiteralType = attributes.getValue("literal");
GlobalInformation.storiesToLitType.put(curStoryId,
curStoryLiteralType);
-
- if (!nameToLitColl.get(curStoryLiteralType).storyToLocations.containsKey(curStoryId)) {
- HashSet<String> insertSet = new HashSet<String>();
- nameToLitColl.get(curStoryLiteralType).storyToLocations.put(
- curStoryId, insertSet);
+ for (SizeBreakdown breakdown : breakdownsForCurFragment()) {
+ if (!breakdown.nameToLitColl.get(curStoryLiteralType).storyToLocations.containsKey(curStoryId)) {
+ HashSet<String> insertSet = new HashSet<String>();
+ breakdown.nameToLitColl.get(curStoryLiteralType).storyToLocations.put(
+ curStoryId, insertSet);
+ }
}
-
} else {
curStoryLiteralType = "";
}
@@ -640,8 +622,8 @@
* This method assigns strings to the appropriate category
*/
private void updateLitTypes(
- final TreeMap<String, LiteralsCollection> nameToLitColl,
- String value, int numBytes) {
+ final Map<String, LiteralsCollection> nameToLitColl, String value,
+ int numBytes) {
int iNumCounted = 0;
@@ -722,9 +704,7 @@
insertSet);
}
}
- }
-
- else {
+ } else {
// note that this will double-count (i.e., it will count a literal
// twice if it's in the output twice), as it should.
nameToLitColl.get(relLitType).cumSize += numBytes;