Have the compiler emit a hopefully reasonable measure of script
size for applications that use GWT.runAsync and thus include a large
number of code fragments in the output.
Review by: jat
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@5076 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/Link.java b/dev/core/src/com/google/gwt/dev/Link.java
index bd03f86..e4284b4 100644
--- a/dev/core/src/com/google/gwt/dev/Link.java
+++ b/dev/core/src/com/google/gwt/dev/Link.java
@@ -27,6 +27,7 @@
import com.google.gwt.dev.cfg.ModuleDefLoader;
import com.google.gwt.dev.cfg.StaticPropertyOracle;
import com.google.gwt.dev.jjs.JJSOptions;
+import com.google.gwt.dev.jjs.impl.CodeSplitter;
import com.google.gwt.dev.util.FileBackedObject;
import com.google.gwt.dev.util.Util;
import com.google.gwt.dev.util.arg.ArgHandlerExtraDir;
@@ -240,6 +241,66 @@
}
compilation.addSelectionPermutation(unboundProperties);
}
+ logScriptSize(logger, perm.getId(), compilation);
+ }
+
+ /**
+ * <p>
+ * Computes and logs the "maximum total script size" for this permutation. The
+ * total script size for one sequence of split points reached is the sum of
+ * the scripts that are downloaded for that sequence. The maximum total script
+ * size is the maximum such size for all possible sequences of split points.
+ * </p>
+ */
+ private static void logScriptSize(TreeLogger logger, int permId,
+ StandardCompilationResult compilation) {
+ /*
+ * The total script size is fully determined by the first split point that
+ * is reached; the order that the remaining are reached doesn't matter. To
+ * find the maximum, divide the sum into two parts: first add the initial
+ * and exclusive fragments, and then calculate the adjustment that should be
+ * applied depending on which split point comes first. Choose among these
+ * adjustments the one that is largest.
+ */
+
+ String[] javaScript = compilation.getJavaScript();
+ int numSplitPoints = CodeSplitter.numSplitPointsForFragments(javaScript.length);
+ int maxTotalSize;
+
+ if (numSplitPoints == 0) {
+ maxTotalSize = javaScript[0].length();
+ } else {
+ // Add up the initial and exclusive fragments
+ maxTotalSize = javaScript[0].length();
+ for (int sp = 1; sp <= numSplitPoints; sp++) {
+ int excl = CodeSplitter.getExclusiveFragmentNumber(sp, numSplitPoints);
+ maxTotalSize += javaScript[excl].length();
+ }
+
+ // Find the largest adjustment for any split point
+ boolean first = true;
+ int adjustment = 0;
+
+ for (int sp = 1; sp <= numSplitPoints; sp++) {
+ int excl = CodeSplitter.getExclusiveFragmentNumber(sp, numSplitPoints);
+ int base = CodeSplitter.getBaseFragmentNumber(sp, numSplitPoints);
+ int leftovers = CodeSplitter.getLeftoversFragmentNumber(sp,
+ numSplitPoints);
+ int thisAdjustment = javaScript[base].length()
+ + javaScript[leftovers].length() - javaScript[excl].length();
+ if (first || (thisAdjustment > adjustment)) {
+ adjustment = thisAdjustment;
+ }
+ first = false;
+ }
+
+ maxTotalSize += adjustment;
+ }
+
+ logger.log(TreeLogger.DEBUG, "Permutation " + permId + " (strong name "
+ + compilation.getStrongName() + ") has an initial download size of "
+ + javaScript[0].length() + " and max total script size of "
+ + maxTotalSize);
}
private final LinkOptionsImpl options;
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/CodeSplitter.java b/dev/core/src/com/google/gwt/dev/jjs/impl/CodeSplitter.java
index a44816d..2304cad 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/CodeSplitter.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/CodeSplitter.java
@@ -227,6 +227,28 @@
new CodeSplitter(logger, jprogram, jsprogram, map).execImpl();
}
+ public static int getBaseFragmentNumber(int sp, int numSplitPoints) {
+ return numSplitPoints + 2 * sp - 1;
+ }
+
+ public static int getExclusiveFragmentNumber(int splitPoint,
+ int numSplitPoints) {
+ return splitPoint;
+ }
+
+ public static int getLeftoversFragmentNumber(int splitPoint,
+ int numSplitPoints) {
+ return numSplitPoints + 2 * splitPoint;
+ }
+
+ /**
+ * Infer the number of split points for a given number of code fragments.
+ */
+ public static int numSplitPointsForFragments(int codeFragments) {
+ assert (((codeFragments - 1) % 3) == 0);
+ return (codeFragments - 1) / 3;
+ }
+
private static Map<JField, JClassLiteral> buildFieldToClassLiteralMap(
JProgram jprogram) {
final Map<JField, JClassLiteral> map = new HashMap<JField, JClassLiteral>();