mirror of
https://github.com/konsoletyper/teavm.git
synced 2024-11-21 01:00:54 +08:00
Add option to print size statistics of generated JS code
This commit is contained in:
parent
614f95d376
commit
168bf1fa9c
@ -15,12 +15,18 @@
|
||||
*/
|
||||
package org.teavm.backend.javascript;
|
||||
|
||||
import com.carrotsearch.hppc.ObjectIntHashMap;
|
||||
import com.carrotsearch.hppc.ObjectIntMap;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Writer;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@ -83,6 +89,9 @@ import org.teavm.vm.spi.RendererListener;
|
||||
import org.teavm.vm.spi.TeaVMHostExtension;
|
||||
|
||||
public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
|
||||
private static final NumberFormat STATS_NUM_FORMAT = new DecimalFormat("#,##0");
|
||||
private static final NumberFormat STATS_PERCENT_FORMAT = new DecimalFormat("0.000 %");
|
||||
|
||||
private TeaVMTargetController controller;
|
||||
private boolean minifying = true;
|
||||
private final Map<MethodReference, Generator> methodGenerators = new HashMap<>();
|
||||
@ -285,6 +294,7 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
|
||||
for (RendererListener listener : rendererListeners) {
|
||||
listener.begin(renderer, target);
|
||||
}
|
||||
int start = sourceWriter.getOffset();
|
||||
sourceWriter.append("\"use strict\";").newLine();
|
||||
renderer.renderRuntime();
|
||||
renderer.render(clsNodes);
|
||||
@ -300,11 +310,46 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
|
||||
for (RendererListener listener : rendererListeners) {
|
||||
listener.complete();
|
||||
}
|
||||
int totalSize = sourceWriter.getOffset() - start;
|
||||
printStats(renderer, totalSize);
|
||||
} catch (IOException e) {
|
||||
throw new RenderingException("IO Error occured", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void printStats(Renderer renderer, int totalSize) {
|
||||
if (!Boolean.parseBoolean(System.getProperty("teavm.js.stats", "false"))) {
|
||||
return;
|
||||
}
|
||||
|
||||
System.out.println("Total output size: " + STATS_NUM_FORMAT.format(totalSize));
|
||||
System.out.println("Metadata size: " + getSizeWithPercentage(renderer.getMetadataSize(), totalSize));
|
||||
System.out.println("String pool size: " + getSizeWithPercentage(renderer.getStringPoolSize(), totalSize));
|
||||
|
||||
ObjectIntMap<String> packageSizeMap = new ObjectIntHashMap<>();
|
||||
for (String className : renderer.getClassesInStats()) {
|
||||
String packageName = className.substring(0, className.lastIndexOf('.') + 1);
|
||||
int classSize = renderer.getClassSize(className);
|
||||
packageSizeMap.put(packageName, packageSizeMap.getOrDefault(packageName, 0) + classSize);
|
||||
}
|
||||
|
||||
String[] packageNames = packageSizeMap.keys().toArray(String.class);
|
||||
Arrays.sort(packageNames, Comparator.comparing(p -> -packageSizeMap.getOrDefault(p, 0)));
|
||||
for (String packageName : packageNames) {
|
||||
System.out.println("Package '" + packageName + "' size: "
|
||||
+ getSizeWithPercentage(packageSizeMap.get(packageName), totalSize));
|
||||
}
|
||||
}
|
||||
|
||||
private String getSizeWithPercentage(int size, int totalSize) {
|
||||
return STATS_NUM_FORMAT.format(size) + " (" + STATS_PERCENT_FORMAT.format((double) size / totalSize) + ")";
|
||||
}
|
||||
|
||||
static class PackageNode {
|
||||
String name;
|
||||
Map<String, PackageNode> children = new HashMap<>();
|
||||
}
|
||||
|
||||
private List<ClassNode> modelToAst(ListableClassHolderSource classes) {
|
||||
AsyncMethodFinder asyncFinder = new AsyncMethodFinder(controller.getDependencyInfo().getCallGraph(),
|
||||
controller.getDiagnostics());
|
||||
|
@ -19,4 +19,6 @@ public interface LocationProvider {
|
||||
int getLine();
|
||||
|
||||
int getColumn();
|
||||
|
||||
int getOffset();
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ public class SourceWriter implements Appendable, LocationProvider {
|
||||
private final int lineWidth;
|
||||
private int column;
|
||||
private int line;
|
||||
private int offset;
|
||||
|
||||
SourceWriter(NamingStrategy naming, Appendable innerWriter, int lineWidth) {
|
||||
this.naming = naming;
|
||||
@ -62,6 +63,7 @@ public class SourceWriter implements Appendable, LocationProvider {
|
||||
newLine();
|
||||
} else {
|
||||
column++;
|
||||
offset++;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@ -92,6 +94,7 @@ public class SourceWriter implements Appendable, LocationProvider {
|
||||
}
|
||||
appendIndent();
|
||||
column += end - start;
|
||||
offset += end - start;
|
||||
innerWriter.append(csq, start, end);
|
||||
}
|
||||
|
||||
@ -149,6 +152,7 @@ public class SourceWriter implements Appendable, LocationProvider {
|
||||
for (int i = 0; i < indentSize; ++i) {
|
||||
innerWriter.append(" ");
|
||||
column += 4;
|
||||
offset += 4;
|
||||
}
|
||||
lineStart = false;
|
||||
}
|
||||
@ -158,6 +162,7 @@ public class SourceWriter implements Appendable, LocationProvider {
|
||||
innerWriter.append('\n');
|
||||
column = 0;
|
||||
++line;
|
||||
++offset;
|
||||
lineStart = true;
|
||||
return this;
|
||||
}
|
||||
@ -169,6 +174,7 @@ public class SourceWriter implements Appendable, LocationProvider {
|
||||
if (!minified) {
|
||||
innerWriter.append(' ');
|
||||
column++;
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
@ -185,6 +191,7 @@ public class SourceWriter implements Appendable, LocationProvider {
|
||||
if (!minified) {
|
||||
innerWriter.append('\n');
|
||||
column = 0;
|
||||
++offset;
|
||||
++line;
|
||||
lineStart = true;
|
||||
}
|
||||
@ -214,4 +221,9 @@ public class SourceWriter implements Appendable, LocationProvider {
|
||||
public int getLine() {
|
||||
return line;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOffset() {
|
||||
return offset;
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,8 @@
|
||||
*/
|
||||
package org.teavm.backend.javascript.rendering;
|
||||
|
||||
import com.carrotsearch.hppc.ObjectIntHashMap;
|
||||
import com.carrotsearch.hppc.ObjectIntMap;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
@ -66,6 +68,10 @@ public class Renderer implements RenderingManager {
|
||||
private RenderingContext context;
|
||||
private List<PostponedFieldInitializer> postponedFieldInitializers = new ArrayList<>();
|
||||
|
||||
private ObjectIntMap<String> sizeByClass = new ObjectIntHashMap<>();
|
||||
private int stringPoolSize;
|
||||
private int metadataSize;
|
||||
|
||||
public Renderer(SourceWriter writer, Set<MethodReference> asyncMethods, Set<MethodReference> asyncFamilyMethods,
|
||||
Diagnostics diagnostics, RenderingContext context) {
|
||||
this.naming = context.getNaming();
|
||||
@ -79,6 +85,22 @@ public class Renderer implements RenderingManager {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public int getStringPoolSize() {
|
||||
return stringPoolSize;
|
||||
}
|
||||
|
||||
public int getMetadataSize() {
|
||||
return metadataSize;
|
||||
}
|
||||
|
||||
public String[] getClassesInStats() {
|
||||
return sizeByClass.keys().toArray(String.class);
|
||||
}
|
||||
|
||||
public int getClassSize(String className) {
|
||||
return sizeByClass.getOrDefault(className, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceWriter getWriter() {
|
||||
return writer;
|
||||
@ -133,6 +155,7 @@ public class Renderer implements RenderingManager {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
int start = writer.getOffset();
|
||||
writer.append("$rt_stringPool([");
|
||||
for (int i = 0; i < context.getStringPool().size(); ++i) {
|
||||
if (i > 0) {
|
||||
@ -141,6 +164,7 @@ public class Renderer implements RenderingManager {
|
||||
writer.append('"').append(RenderingUtil.escapeString(context.getStringPool().get(i))).append('"');
|
||||
}
|
||||
writer.append("]);").newLine();
|
||||
stringPoolSize = writer.getOffset() - start;
|
||||
} catch (IOException e) {
|
||||
throw new RenderingException("IO error", e);
|
||||
}
|
||||
@ -149,14 +173,21 @@ public class Renderer implements RenderingManager {
|
||||
public void renderStringConstants() throws RenderingException {
|
||||
try {
|
||||
for (PostponedFieldInitializer initializer : postponedFieldInitializers) {
|
||||
int start = writer.getOffset();
|
||||
writer.appendStaticField(initializer.field).ws().append("=").ws()
|
||||
.append(context.constantToString(initializer.value)).append(";").softNewLine();
|
||||
int sz = writer.getOffset() - start;
|
||||
appendClassSize(initializer.field.getClassName(), sz);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RenderingException("IO error", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void appendClassSize(String className, int sz) {
|
||||
sizeByClass.put(className, sizeByClass.getOrDefault(className, 0) + sz);
|
||||
}
|
||||
|
||||
public void renderRuntime() throws RenderingException {
|
||||
try {
|
||||
renderSetCloneMethod();
|
||||
@ -291,8 +322,10 @@ public class Renderer implements RenderingManager {
|
||||
}
|
||||
}
|
||||
for (ClassNode cls : classes) {
|
||||
int start = writer.getOffset();
|
||||
renderDeclaration(cls);
|
||||
renderMethodBodies(cls);
|
||||
appendClassSize(cls.getName(), writer.getOffset() - start);
|
||||
}
|
||||
renderClassMetadata(classes);
|
||||
}
|
||||
@ -452,6 +485,7 @@ public class Renderer implements RenderingManager {
|
||||
}
|
||||
|
||||
private void renderClassMetadata(List<ClassNode> classes) {
|
||||
int start = writer.getOffset();
|
||||
try {
|
||||
writer.append("$rt_metadata([");
|
||||
boolean first = true;
|
||||
@ -506,6 +540,8 @@ public class Renderer implements RenderingManager {
|
||||
} catch (IOException e) {
|
||||
throw new RenderingException("IO error occurred", e);
|
||||
}
|
||||
|
||||
metadataSize = writer.getOffset() - start;
|
||||
}
|
||||
|
||||
private void collectMethodsToCopyFromInterfaces(ClassReader cls, List<MethodReference> targetList) {
|
||||
|
Loading…
Reference in New Issue
Block a user