Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 /// Command-line tool to show the size distribution of generated code among | 5 /// Command-line tool to show the size distribution of generated code among |
| 6 /// libraries. Libraries can be grouped using regular expressions. You can | 6 /// libraries. Libraries can be grouped using regular expressions. You can |
| 7 /// specify what regular expressions to use by providing a `grouping.yaml` file. | 7 /// specify what regular expressions to use by providing a `grouping.yaml` file. |
| 8 /// The format of the `grouping.yaml` file is as follows: | 8 /// The format of the `grouping.yaml` file is as follows: |
| 9 /// ```yaml | 9 /// ```yaml |
| 10 /// groups: | 10 /// groups: |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 23 /// specification implicitly defines several groups, one per observed name. | 23 /// specification implicitly defines several groups, one per observed name. |
| 24 /// | 24 /// |
| 25 /// * cluster (optional): a clustering index for how data is shown in a table. | 25 /// * cluster (optional): a clustering index for how data is shown in a table. |
| 26 /// Groups with higher cluster indices are shown later in the table after a | 26 /// Groups with higher cluster indices are shown later in the table after a |
| 27 /// dividing line. If missing, the cluster index defaults to 0. | 27 /// dividing line. If missing, the cluster index defaults to 0. |
| 28 /// | 28 /// |
| 29 /// Here is an example configuration, with comments about what each entry does: | 29 /// Here is an example configuration, with comments about what each entry does: |
| 30 /// | 30 /// |
| 31 /// ```yaml | 31 /// ```yaml |
| 32 /// groups: | 32 /// groups: |
| 33 /// # This group shows the total size of all libraries together, it is shown in | |
| 34 /// # cluster #3, which happens to be the last cluster in this example: | |
| 35 /// - name: "Total (excludes preambles, statics & consts)" | |
| 36 /// regexp: ".*" | |
| 37 /// cluster: 3 | |
| 38 /// | |
| 39 /// # This group shows the total size for all libraries that were loaded from | 33 /// # This group shows the total size for all libraries that were loaded from |
| 40 /// # file:// urls: | 34 /// # file:// urls, it is shown in cluster #2, which happens to be the last |
| 35 /// # cluster in this example before the totals are shown: | |
| 41 /// - { name: "Loose files", regexp: "file://.*", cluster: 2} | 36 /// - { name: "Loose files", regexp: "file://.*", cluster: 2} |
| 42 /// | 37 /// |
| 43 /// # This group shows the total size of all code loaded from packages: | 38 /// # This group shows the total size of all code loaded from packages: |
| 44 /// - { name: "All packages", regexp: "package:.*", cluster: 2} | 39 /// - { name: "All packages", regexp: "package:.*", cluster: 2} |
| 45 /// | 40 /// |
| 46 /// # This group shows the total size of all code loaded from core libraries: | 41 /// # This group shows the total size of all code loaded from core libraries: |
| 47 /// - { name: "Core libs", regexp: "dart:.*", cluster: 2} | 42 /// - { name: "Core libs", regexp: "dart:.*", cluster: 2} |
| 48 /// | 43 /// |
| 49 /// # This group shows the total size of all libraries in a single package. Here | 44 /// # This group shows the total size of all libraries in a single package. Here |
| 50 /// # we omitted the `name` entry, instead we extract it from the regexp | 45 /// # we omitted the `name` entry, instead we extract it from the regexp |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 86 ? new File(args[1]).readAsStringSync() : defaultGrouping; | 81 ? new File(args[1]).readAsStringSync() : defaultGrouping; |
| 87 var groupingYaml = loadYaml(groupingText); | 82 var groupingYaml = loadYaml(groupingText); |
| 88 var groups = []; | 83 var groups = []; |
| 89 for (var group in groupingYaml['groups']) { | 84 for (var group in groupingYaml['groups']) { |
| 90 groups.add(new _Group(group['name'], | 85 groups.add(new _Group(group['name'], |
| 91 new RegExp(group['regexp']), | 86 new RegExp(group['regexp']), |
| 92 group['cluster'] ?? 0)); | 87 group['cluster'] ?? 0)); |
| 93 } | 88 } |
| 94 | 89 |
| 95 var sizes = {}; | 90 var sizes = {}; |
| 91 var allLibs = 0; | |
| 96 for (LibraryInfo lib in info.libraries) { | 92 for (LibraryInfo lib in info.libraries) { |
| 93 allLibs += lib.size; | |
| 97 groups.forEach((group) { | 94 groups.forEach((group) { |
| 98 var match = group.matcher.firstMatch('${lib.uri}'); | 95 var match = group.matcher.firstMatch('${lib.uri}'); |
| 99 if (match != null) { | 96 if (match != null) { |
| 100 var name = group.name; | 97 var name = group.name; |
| 101 if (name == null && match.groupCount > 0) name = match.group(1); | 98 if (name == null && match.groupCount > 0) name = match.group(1); |
| 102 if (name == null) name = match.group(0); | 99 if (name == null) name = match.group(0); |
| 103 sizes.putIfAbsent(name, () => new _SizeEntry(name, group.cluster)); | 100 sizes.putIfAbsent(name, () => new _SizeEntry(name, group.cluster)); |
| 104 sizes[name].size += lib.size; | 101 sizes[name].size += lib.size; |
| 105 } | 102 } |
| 106 }); | 103 }); |
| 107 } | 104 } |
| 108 | 105 |
| 106 var allConstants = 0; | |
| 107 for (var constant in info.constants) { | |
| 108 allConstants += constant.size; | |
| 109 } | |
| 110 | |
| 109 var all = sizes.keys.toList(); | 111 var all = sizes.keys.toList(); |
| 110 all.sort((a, b) => sizes[a].compareTo(sizes[b])); | 112 all.sort((a, b) => sizes[a].compareTo(sizes[b])); |
| 111 var realTotal = info.program.size; | 113 var realTotal = info.program.size; |
| 112 var longest = all.fold(0, (count, value) => max(count, value.length)); | 114 var longest = 0; |
|
Harry Terkelsen
2015/08/19 17:41:31
var longest = 'Program Size'.length;
and then rem
Siggi Cherem (dart-lang)
2015/08/19 19:31:15
Ah - sorry, I meant to remove that line :) - it's
| |
| 115 var rows = []; | |
| 113 longest = max(longest, 'Program Size'.length); | 116 longest = max(longest, 'Program Size'.length); |
| 117 _addRow(String label, int value) { | |
| 118 rows.add(new _Row(label, value)); | |
| 119 longest = max(longest, label.length); | |
| 120 } | |
| 121 | |
| 122 _printRow(_Row row) { | |
| 123 if (row is _Divider) { | |
| 124 print(' ' + ('-' * (longest + 18))); | |
| 125 return; | |
| 126 } | |
| 127 | |
| 128 var percent = row.value == realTotal ? '100' | |
| 129 : (row.value * 100 / realTotal).toStringAsFixed(2); | |
| 130 print(' ${_pad(row.label, longest + 1, right: true)}' | |
| 131 ' ${_pad(row.value, 8)} ${_pad(percent, 6)}%'); | |
| 132 } | |
| 133 | |
| 114 var lastCluster = 0; | 134 var lastCluster = 0; |
| 115 for (var name in all) { | 135 for (var name in all) { |
| 116 var entry = sizes[name]; | 136 var entry = sizes[name]; |
| 117 if (lastCluster < entry.cluster) { | 137 if (lastCluster < entry.cluster) { |
| 118 print(' ' + ('-' * (longest + 18))); | 138 rows.add(const _Divider()); |
| 119 lastCluster = entry.cluster; | 139 lastCluster = entry.cluster; |
| 120 } | 140 } |
| 121 var size = entry.size; | 141 var size = entry.size; |
| 122 var percent = (size * 100 / realTotal).toStringAsFixed(2); | 142 _addRow(name, size); |
| 123 print(' ${_pad(name, longest + 1, right: true)}' | |
| 124 ' ${_pad(size, 8)} ${_pad(percent, 6)}%'); | |
| 125 } | 143 } |
| 126 print(' ${_pad("Program Size", longest + 1, right: true)}' | 144 rows.add(const _Divider()); |
| 127 ' ${_pad(realTotal, 8)} ${_pad(100, 6)}%'); | 145 _addRow("All libraries (excludes preambles, statics & consts)", allLibs); |
| 146 _addRow("Shared consts", allConstants); | |
| 147 _addRow("Total accounted", allLibs + allConstants); | |
| 148 _addRow("Program Size", realTotal); | |
| 149 rows.forEach(_printRow); | |
| 128 } | 150 } |
| 129 | 151 |
| 130 /// A group defined in the configuration. | 152 /// A group defined in the configuration. |
| 131 class _Group { | 153 class _Group { |
| 132 /// Name of the group. May be null if the name is derived from the matcher. In | 154 /// Name of the group. May be null if the name is derived from the matcher. In |
| 133 /// that case, the name would be group(1) of the matched expression if it | 155 /// that case, the name would be group(1) of the matched expression if it |
| 134 /// exist, or group(0) otherwise. | 156 /// exist, or group(0) otherwise. |
| 135 final String name; | 157 final String name; |
| 136 | 158 |
| 137 /// Regular expression matching members of the group. | 159 /// Regular expression matching members of the group. |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 149 final String name; | 171 final String name; |
| 150 final int cluster; | 172 final int cluster; |
| 151 int size = 0; | 173 int size = 0; |
| 152 | 174 |
| 153 _SizeEntry(this.name, this.cluster); | 175 _SizeEntry(this.name, this.cluster); |
| 154 | 176 |
| 155 int compareTo(_SizeEntry other) => | 177 int compareTo(_SizeEntry other) => |
| 156 cluster == other.cluster ? size - other.size : cluster - other.cluster; | 178 cluster == other.cluster ? size - other.size : cluster - other.cluster; |
| 157 } | 179 } |
| 158 | 180 |
| 181 class _Row { | |
| 182 final String label; | |
| 183 final int value; | |
| 184 const _Row(this.label, this.value); | |
| 185 } | |
| 186 | |
| 187 class _Divider extends _Row { | |
| 188 const _Divider() : super('', 0); | |
| 189 } | |
| 190 | |
| 159 _pad(value, n, {bool right: false}) { | 191 _pad(value, n, {bool right: false}) { |
| 160 var s = '$value'; | 192 var s = '$value'; |
| 161 if (s.length >= n) return s; | 193 if (s.length >= n) return s; |
| 162 var pad = ' ' * (n - s.length); | 194 var pad = ' ' * (n - s.length); |
| 163 return right ? '$s$pad' : '$pad$s'; | 195 return right ? '$s$pad' : '$pad$s'; |
| 164 } | 196 } |
| 165 | 197 |
| 166 /// Default grouping specification that includes an entry per library, and | 198 /// Default grouping specification that includes an entry per library, and |
| 167 /// grouping entries for each package, all packages, all core libs, and loose | 199 /// grouping entries for each package, all packages, all core libs, and loose |
| 168 /// files. | 200 /// files. |
| 169 final defaultGrouping = """ | 201 final defaultGrouping = """ |
| 170 groups: | 202 groups: |
| 171 - { name: "Total (excludes preambles, statics & consts)", regexp: ".*", cluster: 3} | |
| 172 - { name: "Loose files", regexp: "file://.*", cluster: 2} | 203 - { name: "Loose files", regexp: "file://.*", cluster: 2} |
| 173 - { name: "All packages", regexp: "package:.*", cluster: 2} | 204 - { name: "All packages", regexp: "package:.*", cluster: 2} |
| 174 - { name: "Core libs", regexp: "dart:.*", cluster: 2} | 205 - { name: "Core libs", regexp: "dart:.*", cluster: 2} |
| 175 # We omitted `name` to extract the group name from the regexp directly. | 206 # We omitted `name` to extract the group name from the regexp directly. |
| 176 # Here the name is the name of the package: | 207 # Here the name is the name of the package: |
| 177 - { regexp: "package:([^/]*)", cluster: 1} | 208 - { regexp: "package:([^/]*)", cluster: 1} |
| 178 # Here the name is the url of the package and dart core libraries: | 209 # Here the name is the url of the package and dart core libraries: |
| 179 - { regexp: "package:.*"} | 210 - { regexp: "package:.*"} |
| 180 - { regexp: "dart:.*"} | 211 - { regexp: "dart:.*"} |
| 181 # Here the name is the relative path of loose files: | 212 # Here the name is the relative path of loose files: |
| 182 - { regexp: "file://${Directory.current.path}/(.*)" } | 213 - { regexp: "file://${Directory.current.path}/(.*)" } |
| 183 """; | 214 """; |
| OLD | NEW |