Skip to content
This repository has been archived by the owner on Aug 11, 2021. It is now read-only.

Commit

Permalink
add tool to get breakdown of deferred libraries by size
Browse files Browse the repository at this point in the history
R=sigmund@google.com

Review URL: https://codereview.chromium.org//2201903004 .
  • Loading branch information
harryterkelsen committed Aug 2, 2016
1 parent 44ab8ea commit 75d3e7b
Show file tree
Hide file tree
Showing 13 changed files with 135 additions and 38 deletions.
1 change: 1 addition & 0 deletions .gitignore
@@ -1,6 +1,7 @@
.buildlog
.DS_Store
.idea
*.iml
.pub/
.settings/
build/
Expand Down
31 changes: 31 additions & 0 deletions README.md
Expand Up @@ -73,6 +73,10 @@ The following tools are a available today:
was split into deferred parts as expected. This tool takes a specification
of the expected layout of code into deferred parts, and checks that the
output from `dart2js` meets the specification.

* [`deferred_library_size`][deferred_size]: a tool that gives a breakdown of
the sizes of the deferred parts of the program. This can show how much of
your total code size can be loaded deferred.

* [`function_size_analysis`][function_analysis]: a tool that shows how much
code was attributed to each function. This tool also uses dependency
Expand Down Expand Up @@ -240,6 +244,32 @@ are the same as the name given to the deferred import in the dart file. For
instance, if you have `import 'package:foo/bar.dart' deferred as baz;` in your
dart file, then the corresponding name in the specification file is 'baz'.

### Deferred library size tool

This tool gives a breakdown of all of the deferred code in the program by size.
It can show how much of the total code size is deferred. It can be run as
follows:

```bash
pub global activate dart2js_info # only needed once
dart2js_info_deferred_library_size out.js.info.json
```

The tool will output a table listing all of the deferred imports in the program
as well as the "main" chunk, which is not deferred. The output looks like:

```
Size by library
------------------------------------------------
main 12345678
foo 7654321
bar 1234567
------------------------------------------------
Main chunk size 12345678
Deferred code size 8888888
Percent of code deferred 41.86%
```

### Function size analysis tool

This command-line tool presents how much each function contributes to the total
Expand Down Expand Up @@ -321,6 +351,7 @@ bugs at the [issue tracker][tracker].
[code_deps]: https://github.com/dart-lang/dart2js_info/blob/master/bin/code_deps.dart
[lib_split]: https://github.com/dart-lang/dart2js_info/blob/master/bin/library_size_split.dart
[deferred_lib]: https://github.com/dart-lang/dart2js_info/blob/master/bin/deferred_library_check.dart
[deferred_size]: https://github.com/dart-lang/dart2js_info/blob/master/bin/deferred_library_size.dart
[coverage]: https://github.com/dart-lang/dart2js_info/blob/master/bin/coverage_log_server.dart
[live]: https://github.com/dart-lang/dart2js_info/blob/master/bin/live_code_size_analysis.dart
[function_analysis]: https://github.com/dart-lang/dart2js_info/blob/master/bin/function_size_analysis.dart
Expand Down
12 changes: 2 additions & 10 deletions bin/code_deps.dart
Expand Up @@ -26,14 +26,13 @@
library dart2js_info.bin.code_deps;

import 'dart:collection';
import 'dart:convert';
import 'dart:io';

import 'package:dart2js_info/info.dart';
import 'package:dart2js_info/src/graph.dart';
import 'package:dart2js_info/src/util.dart';

main(args) {
main(args) async {
if (args.length < 2) {
print('usage: dart2js_info_code_deps path-to.info.json <query>');
print(' where <query> can be:');
Expand All @@ -42,14 +41,7 @@ main(args) {
exit(1);
}

var json;
try {
json = JSON.decode(new File(args[0]).readAsStringSync());
} catch (e) {
print('error: could not read ${args[0]}');
exit(1);
}
var info = new AllInfoJsonCodec().decode(json);
var info = await infoFromFile(args.first);
var graph = graphFromInfo(info);

var queryName = args[1];
Expand Down
2 changes: 1 addition & 1 deletion bin/coverage_log_server.dart
Expand Up @@ -136,7 +136,7 @@ class _Server {
}

// Handle POST requests to record coverage data, and GET requests to display
// the currently coverage resutls.
// the currently coverage results.
if (urlPath == _expectedPath('coverage')) {
if (request.method == 'GET') {
return new shelf.Response.ok(_serializedData, headers: TEXT_HEADERS);
Expand Down
7 changes: 2 additions & 5 deletions bin/debug_info.dart
Expand Up @@ -6,23 +6,20 @@
/// that it is consistent and that it covers all the data we expect it to cover.
library dart2js_info.bin.debug_info;

import 'dart:convert';
import 'dart:io';

import 'package:dart2js_info/info.dart';
import 'package:dart2js_info/src/graph.dart';
import 'package:dart2js_info/src/util.dart';

main(args) {
main(args) async {
if (args.length < 1) {
print('usage: dart tool/debug_info.dart path-to-info.json '
'[--show-library libname]');
exit(1);
}

var filename = args[0];
var json = JSON.decode(new File(filename).readAsStringSync());
var info = new AllInfoJsonCodec().decode(json);
var info = await infoFromFile(args.first);
var debugLibName;

if (args.length > 2 && args[1] == '--show-library') {
Expand Down
8 changes: 1 addition & 7 deletions bin/deferred_library_check.dart
Expand Up @@ -36,11 +36,10 @@
library dart2js_info.bin.deferred_library_check;

import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:dart2js_info/info.dart';
import 'package:dart2js_info/deferred_library_check.dart';
import 'package:dart2js_info/src/util.dart';
import 'package:yaml/yaml.dart';

Future main(List<String> args) async {
Expand All @@ -56,11 +55,6 @@ Future main(List<String> args) async {
if (failures.isNotEmpty) exitCode = 1;
}

Future<AllInfo> infoFromFile(String fileName) async {
var file = await new File(fileName).readAsString();
return new AllInfoJsonCodec().decode(JSON.decode(file));
}

Future manifestFromFile(String fileName) async {
var file = await new File(fileName).readAsString();
return loadYaml(file);
Expand Down
76 changes: 76 additions & 0 deletions bin/deferred_library_size.dart
@@ -0,0 +1,76 @@
// 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:dart2js_info/info.dart';
import 'package:dart2js_info/src/util.dart';

main(args) async {
// TODO(het): Would be faster to only parse the 'outputUnits' part
var info = await infoFromFile(args.first);
var sizeByImport = getSizeByImport(info);
printSizes(sizeByImport, info.program.size);
}

class ImportSize {
final String import;
final int size;

const ImportSize(this.import, this.size);

String toString() {
return '$import: $size';
}
}

void printSizes(Map<String, int> sizeByImport, int programSize) {
var importSizes = <ImportSize>[];
sizeByImport.forEach((import, size) {
importSizes.add(new ImportSize(import, size));
});
// Sort by size, largest first.
importSizes.sort((a, b) => b.size - a.size);
var 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));

var mainChunkSize = sizeByImport['main'];
var deferredSize = programSize - mainChunkSize;
var 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 (var outputUnit in info.outputUnits) {
if (outputUnit.name == 'main' || outputUnit.name == null) {
sizeByImport['main'] = outputUnit.size;
} else {
for (var import in outputUnit.imports) {
sizeByImport.putIfAbsent(import, () => 0);
sizeByImport[import] += outputUnit.size;
}
}
}
return sizeByImport;
}
7 changes: 2 additions & 5 deletions bin/function_size_analysis.dart
Expand Up @@ -6,17 +6,14 @@
/// code.
library compiler.tool.live_code_size_analysis;

import 'dart:convert';
import 'dart:io';
import 'dart:math' as math;

import 'package:dart2js_info/info.dart';
import 'package:dart2js_info/src/graph.dart';
import 'package:dart2js_info/src/util.dart';

main(args) {
var json = JSON.decode(new File(args[0]).readAsStringSync());
var info = new AllInfoJsonCodec().decode(json);
main(args) async {
var info = await infoFromFile(args.first);
showCodeDistribution(info);
}

Expand Down
8 changes: 3 additions & 5 deletions bin/library_size_split.dart
Expand Up @@ -59,23 +59,21 @@
/// This example is very similar to [defaultGrouping].
library dart2js_info.bin.library_size_split;

import 'dart:convert';
import 'dart:io';
import 'dart:math' show max;

import 'package:dart2js_info/info.dart';
import 'package:dart2js_info/src/util.dart';
import 'package:yaml/yaml.dart';

main(args) {
main(args) async {
if (args.length < 1) {
print('usage: dart tool/library_size_split.dart '
'path-to-info.json [grouping.yaml]');
exit(1);
}

var filename = args[0];
var json = JSON.decode(new File(filename).readAsStringSync());
var info = new AllInfoJsonCodec().decode(json);
var info = await infoFromFile(args.first);

var groupingText =
args.length > 1 ? new File(args[1]).readAsStringSync() : defaultGrouping;
Expand Down
6 changes: 3 additions & 3 deletions bin/live_code_size_analysis.dart
Expand Up @@ -39,17 +39,17 @@ import 'dart:io';

import 'package:dart2js_info/info.dart';
import 'package:dart2js_info/src/util.dart';

import 'function_size_analysis.dart';

main(args) {
main(args) async {
if (args.length < 2) {
print('usage: dart tool/live_code_size_analysis.dart path-to-info.json '
'path-to-coverage.json [-v]');
exit(1);
}

var json = JSON.decode(new File(args[0]).readAsStringSync());
var info = new AllInfoJsonCodec().decode(json);
var info = await infoFromFile(args.first);
var coverage = JSON.decode(new File(args[1]).readAsStringSync());
var verbose = args.length > 2 && args[2] == '-v';

Expand Down
10 changes: 10 additions & 0 deletions lib/src/util.dart
Expand Up @@ -4,7 +4,12 @@

library dart2js_info.src.util;

import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:dart2js_info/info.dart';

import 'graph.dart';

/// Computes a graph of dependencies from [info].
Expand Down Expand Up @@ -124,3 +129,8 @@ String recursiveDiagnosticString(Measurements measurements, Metric metric) {
helper(metric);
return sb.toString();
}

Future<AllInfo> infoFromFile(String fileName) async {
var file = await new File(fileName).readAsString();
return new AllInfoJsonCodec().decode(JSON.decode(file));
}
3 changes: 2 additions & 1 deletion pubspec.yaml
@@ -1,5 +1,5 @@
name: dart2js_info
version: 0.2.5
version: 0.2.6
description: >
Libraries and tools to process data produced when running dart2js with
--dump-info.
Expand All @@ -24,6 +24,7 @@ executables:
dart2js_info_coverage_log_server: coverage_log_server
dart2js_info_debug_info: debug_info
dart2js_info_deferred_library_check: deferred_library_check
dart2js_info_deferred_library_size: deferred_library_size
dart2js_info_function_size_analysis: function_size_analysis
dart2js_info_library_size_split: library_size_split
dart2js_info_live_code_size_analysis: live_code_size_analysis
2 changes: 1 addition & 1 deletion tool/travis.sh
Expand Up @@ -9,7 +9,7 @@ set -e

# Verify that the libraries are error free.
dartanalyzer --fatal-warnings \
lib/info.dart \
lib/**/*.dart \
test/*.dart

# Run the tests.
Expand Down

0 comments on commit 75d3e7b

Please sign in to comment.