blob: 6cf0ceb480845297ab70d5512f94bac4b53e4cd1 [file] [log] [blame]
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
/// This tool gives a breakdown of code size by deferred part in the program.
library dart2js_info.bin.deferred_library_size;
import 'dart:math';
import 'package:args/command_runner.dart';
import 'package:dart2js_info/info.dart';
import 'package:dart2js_info/src/io.dart';
import 'usage_exception.dart';
/// This tool gives a breakdown of code size by deferred part in the program.
class DeferredLibrarySize extends Command<void> with PrintUsageException {
@override
final String name = "deferred_size";
@override
final String description = "Show breakdown of codesize by deferred part.";
@override
void run() async {
final args = argResults!.rest;
if (args.isEmpty) {
usageException('Missing argument: info.data');
}
// TODO(het): Would be faster to only parse the 'outputUnits' part
final info = await infoFromFile(args.first);
final sizeByImport = getSizeByImport(info);
printSizes(sizeByImport, info.program!.size);
}
}
class ImportSize {
final String import;
final int size;
const ImportSize(this.import, this.size);
@override
String toString() {
return '$import: $size';
}
}
void printSizes(Map<String, int> sizeByImport, int programSize) {
final importSizes = <ImportSize>[];
sizeByImport.forEach((import, size) {
importSizes.add(ImportSize(import, size));
});
// Sort by size, largest first.
importSizes.sort((a, b) => b.size - a.size);
int longest = importSizes.fold('Percent of code deferred'.length,
(longest, importSize) => max(longest, importSize.import.length));
printRow(label, data, {int width = 15}) {
print('${label.toString().padRight(longest + 1)}'
'${data.toString().padLeft(width)}');
}
print('');
print('Size by library');
print('-' * (longest + 16));
for (var importSize in importSizes) {
// TODO(het): split into specific and shared size
printRow(importSize.import, importSize.size);
}
print('-' * (longest + 16));
final mainChunkSize = sizeByImport['main']!;
final deferredSize = programSize - mainChunkSize;
final percentDeferred = (deferredSize * 100 / programSize).toStringAsFixed(2);
printRow('Main chunk size', mainChunkSize);
printRow('Deferred code size', deferredSize);
printRow('Percent of code deferred', '$percentDeferred%');
}
Map<String, int> getSizeByImport(AllInfo info) {
var sizeByImport = <String, int>{};
for (final outputUnit in info.outputUnits) {
if (outputUnit.name == 'main') {
sizeByImport['main'] = outputUnit.size;
} else {
for (final import in outputUnit.imports) {
sizeByImport.update(import, (value) => value + outputUnit.size,
ifAbsent: () => outputUnit.size);
}
}
}
return sizeByImport;
}