[vm/bytecode] Add an option to print bytecode size statistics
This CL adds '--show-bytecode-size-stat' option to gen_kernel and
Fuchsia kernel compiler to print breakdown of size of generated bytecode.
Change-Id: I0637738b0a1e9c635cb687bbfd482a9bdae32183
Reviewed-on: https://dart-review.googlesource.com/c/90322
Commit-Queue: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Régis Crelier <regis@google.com>
Auto-Submit: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Régis Crelier <regis@google.com>
diff --git a/pkg/vm/lib/bytecode/bytecode_serialization.dart b/pkg/vm/lib/bytecode/bytecode_serialization.dart
index a592981..bce0817 100644
--- a/pkg/vm/lib/bytecode/bytecode_serialization.dart
+++ b/pkg/vm/lib/bytecode/bytecode_serialization.dart
@@ -277,6 +277,7 @@
}
void write(BufferedWriter writer) {
+ final start = writer.offset;
writer.writeUInt32(_oneByteStrings.length);
writer.writeUInt32(_twoByteStrings.length);
int endOffset = 0;
@@ -301,6 +302,7 @@
}
}
_written = true;
+ BytecodeSizeStatistics.stringTableSize += (writer.offset - start);
}
StringTable.read(BufferedReader reader) {
@@ -358,3 +360,48 @@
return sb.toString();
}
}
+
+class ConstantPoolEntryStatistics {
+ final String name;
+ int size = 0;
+ int count = 0;
+
+ ConstantPoolEntryStatistics(this.name);
+}
+
+class BytecodeSizeStatistics {
+ static int componentSize = 0;
+ static int objectTableSize = 0;
+ static int stringTableSize = 0;
+ static int membersSize = 0;
+ static int constantPoolSize = 0;
+ static int instructionsSize = 0;
+ static List<ConstantPoolEntryStatistics> constantPoolStats =
+ <ConstantPoolEntryStatistics>[];
+
+ static void reset() {
+ componentSize = 0;
+ objectTableSize = 0;
+ stringTableSize = 0;
+ membersSize = 0;
+ constantPoolSize = 0;
+ instructionsSize = 0;
+ constantPoolStats = <ConstantPoolEntryStatistics>[];
+ }
+
+ static void dump() {
+ print("Bytecode size statistics:");
+ print(" Bytecode component: $componentSize");
+ print(" - object table: $objectTableSize");
+ print(" - string table: $stringTableSize");
+ print(" Bytecode members: $membersSize");
+ print(" - constant pool: $constantPoolSize");
+ for (var cpStat in constantPoolStats) {
+ final name = cpStat.name.padRight(40);
+ final size = cpStat.size.toString().padLeft(10);
+ final count = cpStat.count.toString().padLeft(8);
+ print(" - $name: $size (count: $count)");
+ }
+ print(" - instructions: $instructionsSize");
+ }
+}
diff --git a/pkg/vm/lib/bytecode/constant_pool.dart b/pkg/vm/lib/bytecode/constant_pool.dart
index e4c77c1..a81f5f0 100644
--- a/pkg/vm/lib/bytecode/constant_pool.dart
+++ b/pkg/vm/lib/bytecode/constant_pool.dart
@@ -10,7 +10,12 @@
import 'dbc.dart' show constantPoolIndexLimit, BytecodeLimitExceededException;
import 'bytecode_serialization.dart'
- show BufferedWriter, BufferedReader, StringTable;
+ show
+ BufferedWriter,
+ BufferedReader,
+ BytecodeSizeStatistics,
+ ConstantPoolEntryStatistics,
+ StringTable;
import 'object_table.dart' show ObjectHandle, ObjectTable;
/*
@@ -210,6 +215,9 @@
kInterfaceCall,
}
+String constantTagToString(ConstantTag tag) =>
+ tag.toString().substring('ConstantTag.k'.length);
+
abstract class ConstantPoolEntry {
const ConstantPoolEntry();
@@ -1303,13 +1311,28 @@
}
void write(BufferedWriter writer) {
+ final start = writer.offset;
+ if (BytecodeSizeStatistics.constantPoolStats.isEmpty) {
+ for (var tag in ConstantTag.values) {
+ BytecodeSizeStatistics.constantPoolStats
+ .add(new ConstantPoolEntryStatistics(constantTagToString(tag)));
+ }
+ }
writer.writePackedUInt30(entries.length);
entries.forEach((e) {
if (e is _ReservedConstantPoolEntry) {
return;
}
+
+ final entryStart = writer.offset;
+
e.write(writer);
+
+ final entryStat = BytecodeSizeStatistics.constantPoolStats[e.tag.index];
+ entryStat.size += (writer.offset - entryStart);
+ ++entryStat.count;
});
+ BytecodeSizeStatistics.constantPoolSize += (writer.offset - start);
}
ConstantPool.read(BufferedReader reader)
diff --git a/pkg/vm/lib/bytecode/object_table.dart b/pkg/vm/lib/bytecode/object_table.dart
index 4b17c60..baa1460 100644
--- a/pkg/vm/lib/bytecode/object_table.dart
+++ b/pkg/vm/lib/bytecode/object_table.dart
@@ -12,6 +12,7 @@
BufferedWriter,
BufferedReader,
BytecodeObject,
+ BytecodeSizeStatistics,
ObjectReader,
ObjectWriter,
StringWriter;
@@ -1022,6 +1023,7 @@
void write(BufferedWriter writer) {
assert(writer.objectWriter == this);
assert(_indexTable != null);
+ final start = writer.offset;
BufferedWriter contentsWriter = new BufferedWriter.fromWriter(writer);
List<int> offsets = new List<int>(_indexTable.length);
@@ -1045,6 +1047,7 @@
obj.indexStrings(writer.stringWriter);
}
}
+ BytecodeSizeStatistics.objectTableSize += (writer.offset - start);
}
ObjectTable.read(BufferedReader reader) {
diff --git a/pkg/vm/lib/kernel_front_end.dart b/pkg/vm/lib/kernel_front_end.dart
index 6b50c79..eb56144 100644
--- a/pkg/vm/lib/kernel_front_end.dart
+++ b/pkg/vm/lib/kernel_front_end.dart
@@ -43,6 +43,7 @@
import 'package:kernel/vm/constants_native_effects.dart' as vm_constants;
import 'bytecode/ast_remover.dart' show ASTRemover;
+import 'bytecode/bytecode_serialization.dart' show BytecodeSizeStatistics;
import 'bytecode/gen_bytecode.dart' show generateBytecode;
import 'constants_error_reporter.dart' show ForwardConstantEvaluationErrors;
@@ -106,6 +107,8 @@
help: 'Emit source positions in bytecode', defaultsTo: false);
args.addFlag('drop-ast',
help: 'Drop AST for members with bytecode', defaultsTo: false);
+ args.addFlag('show-bytecode-size-stat',
+ help: 'Show bytecode size breakdown.', defaultsTo: false);
args.addFlag('use-future-bytecode-format',
help: 'Generate bytecode in the bleeding edge format', defaultsTo: false);
args.addMultiOption('enable-experiment',
@@ -151,6 +154,7 @@
final bool enableAsserts = options['enable-asserts'];
final bool enableConstantEvaluation = options['enable-constant-evaluation'];
final bool splitOutputByPackages = options['split-output-by-packages'];
+ final bool showBytecodeSizeStat = options['show-bytecode-size-stat'];
final List<String> experimentalFlags = options['enable-experiment'];
final Map<String, String> environmentDefines = {};
@@ -214,11 +218,19 @@
return compileTimeErrorExitCode;
}
+ if (showBytecodeSizeStat && !splitOutputByPackages) {
+ BytecodeSizeStatistics.reset();
+ }
+
final IOSink sink = new File(outputFileName).openWrite();
final BinaryPrinter printer = new BinaryPrinter(sink);
printer.writeComponentFile(component);
await sink.close();
+ if (showBytecodeSizeStat && !splitOutputByPackages) {
+ BytecodeSizeStatistics.dump();
+ }
+
if (depfile != null) {
await writeDepfile(fileSystem, component, outputFileName, depfile);
}
@@ -233,6 +245,7 @@
genBytecode: genBytecode,
emitBytecodeSourcePositions: emitBytecodeSourcePositions,
dropAST: dropAST,
+ showBytecodeSizeStat: showBytecodeSizeStat,
);
}
@@ -587,6 +600,7 @@
bool genBytecode: false,
bool emitBytecodeSourcePositions: false,
bool dropAST: false,
+ bool showBytecodeSizeStat: false,
bool useFutureBytecodeFormat: false,
}) async {
// Package sharing: make the encoding not depend on the order in which parts
@@ -611,6 +625,10 @@
final List<String> packages = packagesSet.toList();
packages.add('main'); // Make sure main package is last.
+ if (showBytecodeSizeStat) {
+ BytecodeSizeStatistics.reset();
+ }
+
await runWithFrontEndCompilerContext(source, compilerOptions, component,
() async {
for (String package in packages) {
@@ -653,6 +671,10 @@
}
});
+ if (showBytecodeSizeStat) {
+ BytecodeSizeStatistics.dump();
+ }
+
final IOSink packagesList = new File('$outputFileName-packages').openWrite();
for (String package in packages) {
packagesList.writeln(package);
diff --git a/pkg/vm/lib/metadata/bytecode.dart b/pkg/vm/lib/metadata/bytecode.dart
index 7a86c70..cd9f65e 100644
--- a/pkg/vm/lib/metadata/bytecode.dart
+++ b/pkg/vm/lib/metadata/bytecode.dart
@@ -6,7 +6,7 @@
import 'package:kernel/ast.dart';
import '../bytecode/bytecode_serialization.dart'
- show BufferedWriter, BufferedReader, StringTable;
+ show BufferedWriter, BufferedReader, BytecodeSizeStatistics, StringTable;
import '../bytecode/constant_pool.dart' show ConstantPool;
import '../bytecode/dbc.dart'
show
@@ -121,6 +121,7 @@
@override
void write(BufferedWriter writer) {
+ final start = writer.offset;
writer.writePackedUInt30(flags);
if (hasClosures) {
writer.writePackedUInt30(closures.length);
@@ -140,6 +141,7 @@
if (hasClosures) {
closures.forEach((c) => c.bytecode.write(writer));
}
+ BytecodeSizeStatistics.membersSize += (writer.offset - start);
}
factory MemberBytecode.read(BufferedReader reader) {
@@ -368,6 +370,7 @@
@override
void write(BufferedWriter writer) {
+ final start = writer.offset;
objectTable.allocateIndexTable();
// Writing object table may add new strings to strings table,
@@ -384,6 +387,7 @@
writer.writeBytes(stringsWriter.takeBytes());
writer.writeBytes(objectsWriter.takeBytes());
+ BytecodeSizeStatistics.componentSize += (writer.offset - start);
}
BytecodeComponent.read(BufferedReader reader) {
@@ -461,6 +465,7 @@
writer.writePackedUInt30(bytecodes.length);
writer.align(bytecodeInstructionsAlignment);
writer.writeBytes(bytecodes);
+ BytecodeSizeStatistics.instructionsSize += bytecodes.length;
}
List<int> _readBytecodeInstructions(BufferedReader reader) {