| Index: pkg/compiler/tool/library_size_split.dart
|
| diff --git a/pkg/compiler/tool/library_size_split.dart b/pkg/compiler/tool/library_size_split.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..dcfaefeb22ae21b1a4efe5cf69e940ee8cfc02f0
|
| --- /dev/null
|
| +++ b/pkg/compiler/tool/library_size_split.dart
|
| @@ -0,0 +1,132 @@
|
| +// Copyright (c) 2015, 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.
|
| +
|
| +/// Command-line tool to show the size distribution of generated code among
|
| +/// libraries. Libraries can be grouped using regular expressions. See
|
| +/// [defaultGrouping] for an example.
|
| +library compiler.tool.library_size_split;
|
| +
|
| +import 'dart:convert';
|
| +import 'dart:io';
|
| +import 'dart:math' show max;
|
| +
|
| +import 'package:compiler/src/info/info.dart';
|
| +import 'package:yaml/yaml.dart';
|
| +
|
| +main(args) {
|
| + 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 = AllInfo.parseFromJson(json);
|
| +
|
| + var groupingText = args.length > 1
|
| + ? new File(args[1]).readAsStringSync() : defaultGrouping;
|
| + var groupingYaml = loadYaml(groupingText);
|
| + var groups = [];
|
| + for (var group in groupingYaml['groups']) {
|
| + groups.add(new _Group(group['name'],
|
| + new RegExp(group['regexp']),
|
| + group['cluster'] ?? 0));
|
| + }
|
| +
|
| + var sizes = {};
|
| + for (LibraryInfo lib in info.libraries) {
|
| + groups.forEach((group) {
|
| + var match = group.matcher.firstMatch('${lib.uri}');
|
| + if (match != null) {
|
| + var name = group.name;
|
| + if (name == null && match.groupCount > 0) name = match.group(1);
|
| + if (name == null) name = match.group(0);
|
| + sizes.putIfAbsent(name, () => new _SizeEntry(name, group.cluster));
|
| + sizes[name].size += lib.size;
|
| + }
|
| + });
|
| + }
|
| +
|
| + var all = sizes.keys.toList();
|
| + all.sort((a, b) => sizes[a].compareTo(sizes[b]));
|
| + var realTotal = info.program.size;
|
| + var longest = all.fold(0, (count, value) => max(count, value.length));
|
| + longest = max(longest, 'Program Size'.length);
|
| + var lastCluster = 0;
|
| + for (var name in all) {
|
| + var entry = sizes[name];
|
| + if (lastCluster < entry.cluster) {
|
| + print(' ' + ('-' * (longest + 18)));
|
| + lastCluster = entry.cluster;
|
| + }
|
| + var size = entry.size;
|
| + var percent = (size * 100 / realTotal).toStringAsFixed(2);
|
| + print(' ${_pad(name, longest + 1, right: true)}'
|
| + ' ${_pad(size, 8)} ${_pad(percent, 6)}%');
|
| + }
|
| + print(' ${_pad("Program Size", longest + 1, right: true)}'
|
| + ' ${_pad(realTotal, 8)} ${_pad(100, 6)}%');
|
| +}
|
| +
|
| +/// A group defined in the configuration.
|
| +class _Group {
|
| + /// Name of the group. May be null if the name is derived from the matcher. In
|
| + /// that case, the name would be group(1) of the matched expression if it
|
| + /// exist, or group(0) otherwise.
|
| + final String name;
|
| +
|
| + /// Regular expression matching members of the group.
|
| + final RegExp matcher;
|
| +
|
| + /// Index used to cluster groups together. Useful when the grouping
|
| + /// configuration describes some coarser groups than orders (e.g. summary of
|
| + /// packages would be in a different cluster than a summary of libraries).
|
| + final int cluster;
|
| +
|
| + _Group(this.name, this.matcher, this.cluster);
|
| +}
|
| +
|
| +class _SizeEntry {
|
| + final String name;
|
| + final int cluster;
|
| + int size = 0;
|
| +
|
| + _SizeEntry(this.name, this.cluster);
|
| +
|
| + int compareTo(_SizeEntry other) =>
|
| + cluster == other.cluster ? size - other.size : cluster - other.cluster;
|
| +}
|
| +
|
| +_pad(value, n, {bool right: false}) {
|
| + var s = '$value';
|
| + if (s.length >= n) return s;
|
| + var pad = ' ' * (n - s.length);
|
| + return right ? '$s$pad' : '$pad$s';
|
| +}
|
| +
|
| +/// Example grouping specification: a yaml format containing a list of
|
| +/// group specifications. A group is specified by 3 parameters:
|
| +/// - name: the name that will be shown in the table of results
|
| +/// - regexp: a regexp used to match entries that belong to the group
|
| +/// - cluster: a clustering index, the higher the value, the later it will be
|
| +/// shown in the results.
|
| +/// Both cluster and name are optional. If cluster is omitted, the default value
|
| +/// is 0. If the name is omitted, it is extracted from the regexp, either as
|
| +/// group(1) if it is available or group(0) otherwise.
|
| +final defaultGrouping = """
|
| +groups:
|
| +- { name: "Total (excludes preambles, statics & consts)", regexp: ".*", cluster: 3}
|
| +- { name: "Loose files", regexp: "file://.*", cluster: 2}
|
| +- { name: "All packages", regexp: "package:.*", cluster: 2}
|
| +- { name: "Core libs", regexp: "dart:.*", cluster: 2}
|
| +# We omitted `name` to extract the group name from the regexp directly.
|
| +# Here the name is the name of the package:
|
| +- { regexp: "package:([^/]*)", cluster: 1}
|
| +# Here the name is the url of the package and dart core libraries:
|
| +- { regexp: "package:.*"}
|
| +- { regexp: "dart:.*"}
|
| +# Here the name is the relative path of loose files:
|
| +- { regexp: "file://${Directory.current.path}/(.*)" }
|
| +""";
|
|
|