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 /// Measurements collected about individual functions. Currently we compute | 5 /// Measurements collected about individual functions. Currently we compute |
| 6 /// data about "sends", to classify whether we know the target or not. | 6 /// data about "sends", to classify whether we know the target or not. |
| 7 library dart2js_info.src.measurements; | 7 library dart2js_info.src.measurements; |
| 8 | 8 |
| 9 /// Top-level set of metrics | 9 /// Top-level set of metrics |
| 10 const List<Metric> _topLevelMetrics = const [ | 10 const List<Metric> _topLevelMetrics = const [Metric.functions, Metric.send,]; |
| 11 Metric.functions, | |
| 12 Metric.send, | |
| 13 ]; | |
| 14 | 11 |
| 15 /// Apply `f` on each metric in DFS order on the metric tree. [Metric.functions] | 12 /// Apply `f` on each metric in DFS order on the metric tree. [Metric.functions] |
| 16 /// and [Metric.send] are the top level metrics. See those declarations for | 13 /// and [Metric.send] are the top level metrics. See those declarations for |
| 17 /// details on the subtrees. | 14 /// details on the subtrees. |
| 18 visitAllMetrics(f) { | 15 visitAllMetrics(f) { |
| 19 var parentsStack = []; | 16 var parentsStack = []; |
| 20 helper(Metric m) { | 17 helper(Metric m) { |
| 21 f(m, parentsStack); | 18 f(m, parentsStack); |
| 22 if (m is GroupedMetric) { | 19 if (m is GroupedMetric) { |
| 23 parentsStack.add(m); | 20 parentsStack.add(m); |
| 24 m.submetrics.forEach(helper); | 21 m.submetrics.forEach(helper); |
| 25 parentsStack.removeLast(); | 22 parentsStack.removeLast(); |
| 26 } | 23 } |
| 27 } | 24 } |
| 28 _topLevelMetrics.forEach(helper); | 25 _topLevelMetrics.forEach(helper); |
| 29 } | 26 } |
| 30 | 27 |
| 31 /// A metric we intend to measure. | 28 /// A metric we intend to measure. |
| 32 class Metric { | 29 class Metric { |
| 33 /// Name for the metric. | 30 /// Name for the metric. |
| 34 final String name; | 31 final String name; |
| 35 | 32 |
| 36 const Metric(this.name); | 33 const Metric(this.name); |
| 37 | 34 |
| 35 factory Metric.fromName(String name) => _nameToMetricMap[name]; | |
| 36 | |
| 38 String toString() => name; | 37 String toString() => name; |
| 39 | 38 |
| 40 /// Total functions in a library/package/program. Parent of | 39 /// Total functions in a library/package/program. Parent of |
| 41 /// [reachableFunction]. | 40 /// [reachableFunction]. |
| 42 static const Metric functions = const GroupedMetric('functions', const [ | 41 static const Metric functions = |
| 43 reachableFunctions, | 42 const GroupedMetric('functions', const [reachableFunctions,]); |
|
Siggi Cherem (dart-lang)
2015/10/15 23:36:08
remove trailing comma (,) here and below.
Harry Terkelsen
2015/10/15 23:59:55
Done.
| |
| 44 ]); | |
| 45 | 43 |
| 46 /// Subset of the functions that are reachable. | 44 /// Subset of the functions that are reachable. |
| 47 static const Metric reachableFunctions = const Metric('reachable functions'); | 45 static const Metric reachableFunctions = const Metric('reachable functions'); |
| 48 | 46 |
| 49 /// Parent of all send metrics. We classify sends as follows: | 47 /// Parent of all send metrics. We classify sends as follows: |
| 50 /// | 48 /// |
| 51 /// sends | 49 /// sends |
| 52 /// |- monomorphic | 50 /// |- monomorphic |
| 53 /// | |- static (top-levels, statics) | 51 /// | |- static (top-levels, statics) |
| 54 /// | |- super | 52 /// | |- super |
| 55 /// | |- local (access to a local var, call local function) | 53 /// | |- local (access to a local var, call local function) |
| 56 /// | |- constructor (like factory ctros) | 54 /// | |- constructor (like factory ctros) |
| 57 /// | |- type variable (reading a type variable) | 55 /// | |- type variable (reading a type variable) |
| 58 /// | |- nsm (known no such method exception) | 56 /// | |- nsm (known no such method exception) |
| 59 /// | |- single-nsm-call (known no such method call, single target) | 57 /// | |- single-nsm-call (known no such method call, single target) |
| 60 /// | |- instance (non-interceptor, only one possible target) | 58 /// | |- instance (non-interceptor, only one possible target) |
| 61 /// | '- interceptor (interceptor, known) | 59 /// | '- interceptor (interceptor, known) |
| 62 /// | | 60 /// | |
| 63 /// '- polymorphic | 61 /// '- polymorphic |
| 64 /// |- multi-nsm (known to be nSM, but not sure if error, or call, or | 62 /// |- multi-nsm (known to be nSM, but not sure if error, or call, or |
| 65 /// which call) | 63 /// which call) |
| 66 /// |- virtual (traditional virtual call, polymorphic equivalent of | 64 /// |- virtual (traditional virtual call, polymorphic equivalent of |
| 67 /// | `instance`, no-interceptor) | 65 /// | `instance`, no-interceptor) |
| 68 /// |- multi-interceptor (1 of n possible interceptors) | 66 /// |- multi-interceptor (1 of n possible interceptors) |
| 69 /// '- dynamic (any combination of the above) | 67 /// '- dynamic (any combination of the above) |
| 70 /// | 68 /// |
| 71 static const Metric send = const GroupedMetric('send', const [ | 69 static const Metric send = |
| 72 monomorphicSend, | 70 const GroupedMetric('send', const [monomorphicSend, polymorphicSend,]); |
| 73 polymorphicSend, | |
| 74 ]); | |
| 75 | 71 |
| 76 /// Parent of monomorphic sends, see [send] for details. | 72 /// Parent of monomorphic sends, see [send] for details. |
| 77 static const Metric monomorphicSend = const GroupedMetric('monomorphic', | 73 static const Metric monomorphicSend = |
| 78 const [ | 74 const GroupedMetric('monomorphic', const [ |
| 79 staticSend, | 75 staticSend, |
| 80 superSend, | 76 superSend, |
| 81 localSend, | 77 localSend, |
| 82 constructorSend, | 78 constructorSend, |
| 83 typeVariableSend, | 79 typeVariableSend, |
| 84 nsmErrorSend, | 80 nsmErrorSend, |
| 85 singleNsmCallSend, | 81 singleNsmCallSend, |
| 86 instanceSend, | 82 instanceSend, |
| 87 interceptorSend, | 83 interceptorSend, |
| 88 ]); | 84 ]); |
| 89 | 85 |
| 90 /// Metric for static calls, see [send] for details. | 86 /// Metric for static calls, see [send] for details. |
| 91 static const Metric staticSend = const Metric('static'); | 87 static const Metric staticSend = const Metric('static'); |
| 92 | 88 |
| 93 /// Metric for super calls, see [send] for details. | 89 /// Metric for super calls, see [send] for details. |
| 94 static const Metric superSend = const Metric('super'); | 90 static const Metric superSend = const Metric('super'); |
| 95 | 91 |
| 96 /// Metric for local variable sends, see [send] for details. | 92 /// Metric for local variable sends, see [send] for details. |
| 97 static const Metric localSend = const Metric('local'); | 93 static const Metric localSend = const Metric('local'); |
| 98 | 94 |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 112 | 108 |
| 113 /// Metric for calls to a precisely known instance method, see [send] for | 109 /// Metric for calls to a precisely known instance method, see [send] for |
| 114 /// details. | 110 /// details. |
| 115 static const Metric instanceSend = const Metric('instance'); | 111 static const Metric instanceSend = const Metric('instance'); |
| 116 | 112 |
| 117 /// Metric for calls to a precisely known interceptor method, see [send] for | 113 /// Metric for calls to a precisely known interceptor method, see [send] for |
| 118 /// details. | 114 /// details. |
| 119 static const Metric interceptorSend = const Metric('interceptor'); | 115 static const Metric interceptorSend = const Metric('interceptor'); |
| 120 | 116 |
| 121 /// Parent of polymorphic sends, see [send] for details. | 117 /// Parent of polymorphic sends, see [send] for details. |
| 122 static const Metric polymorphicSend = const GroupedMetric('polymorphic', | 118 static const Metric polymorphicSend = const GroupedMetric( |
| 123 const [ | 119 'polymorphic', const [ |
|
Siggi Cherem (dart-lang)
2015/10/15 23:36:08
I would have preferred the old formatting over wha
Harry Terkelsen
2015/10/15 23:59:55
me too
Harry Terkelsen
2015/10/16 00:05:45
looks better with the trailing comma removed
| |
| 124 multiNsmCallSend, | 120 multiNsmCallSend, |
| 125 virtualSend, | 121 virtualSend, |
| 126 multiInterceptorSend, | 122 multiInterceptorSend, |
| 127 dynamicSend, | 123 dynamicSend, |
| 128 ]); | 124 ]); |
| 129 | 125 |
| 130 /// Metric for calls to noSuchMethod methods with more than one possible | 126 /// Metric for calls to noSuchMethod methods with more than one possible |
| 131 /// target, see [send] for details. | 127 /// target, see [send] for details. |
| 132 static const Metric multiNsmCallSend = const Metric('nSM call multi'); | 128 static const Metric multiNsmCallSend = const Metric('nSM call multi'); |
| 133 | 129 |
| 134 /// Metric for calls that are dispatched virtually ar runtime, see [send] for | 130 /// Metric for calls that are dispatched virtually ar runtime, see [send] for |
| 135 /// details. | 131 /// details. |
| 136 static const Metric virtualSend = const Metric('virtual'); | 132 static const Metric virtualSend = const Metric('virtual'); |
| 137 | 133 |
| 138 /// Metyric for calls to more than one possible interceptor, see [send] for | 134 /// Metyric for calls to more than one possible interceptor, see [send] for |
| 139 /// details. | 135 /// details. |
| 140 static const Metric multiInterceptorSend = const Metric('interceptor multi'); | 136 static const Metric multiInterceptorSend = const Metric('interceptor multi'); |
| 141 | 137 |
| 142 /// Metyric for dynamic calls for which we know nothing about the target | 138 /// Metyric for dynamic calls for which we know nothing about the target |
| 143 /// method. See [send] for details. | 139 /// method. See [send] for details. |
| 144 static const Metric dynamicSend = const Metric('dynamic'); | 140 static const Metric dynamicSend = const Metric('dynamic'); |
| 145 | 141 |
| 146 String toJson() => name; | |
| 147 static Map<String, Metric> _nameToMetricMap = () { | 142 static Map<String, Metric> _nameToMetricMap = () { |
| 148 var res = {}; | 143 var res = {}; |
| 149 visitAllMetrics((m, _) => res[m.name] = m); | 144 visitAllMetrics((m, _) => res[m.name] = m); |
| 150 return res; | 145 return res; |
| 151 }(); | 146 }(); |
| 152 | |
| 153 static Metric fromJson(String name) => _nameToMetricMap[name]; | |
| 154 } | 147 } |
| 155 | 148 |
| 156 /// A metric that is subdivided in smaller metrics. | 149 /// A metric that is subdivided in smaller metrics. |
| 157 class GroupedMetric extends Metric { | 150 class GroupedMetric extends Metric { |
| 158 final List<Metric> submetrics; | 151 final List<Metric> submetrics; |
| 159 | 152 |
| 160 const GroupedMetric(String name, this.submetrics) : super(name); | 153 const GroupedMetric(String name, this.submetrics) : super(name); |
| 161 } | 154 } |
| 162 | 155 |
| 163 /// A measurement entry (practically a source-span location where the | 156 /// A measurement entry (practically a source-span location where the |
| 164 /// measurement was seen). | 157 /// measurement was seen). |
| 165 class Entry { | 158 class Entry { |
| 166 final int begin; | 159 final int begin; |
| 167 final int end; | 160 final int end; |
| 168 Entry(this.begin, this.end); | 161 Entry(this.begin, this.end); |
| 169 } | 162 } |
| 170 | 163 |
| 171 /// A collection of data points for each metric. Used to summarize a single | 164 /// A collection of data points for each metric. Used to summarize a single |
| 172 /// function, a library, a package, or an entire program. | 165 /// function, a library, a package, or an entire program. |
| 173 class Measurements { | 166 class Measurements { |
| 174 final Uri uri; | 167 final Uri uri; |
| 175 final Map<Metric, List<Entry>> entries; | 168 final Map<Metric, List<Entry>> entries; |
| 176 final Map<Metric, int> counters; | 169 final Map<Metric, int> counters; |
| 177 | 170 |
| 178 Measurements([this.uri]) | 171 Measurements([this.uri]) |
| 179 : entries = <Metric, List<Entry>>{}, | 172 : entries = <Metric, List<Entry>>{}, |
| 180 counters = <Metric, int>{}; | 173 counters = <Metric, int>{}; |
| 181 | 174 |
| 182 const Measurements.unreachableFunction() | 175 const Measurements.unreachableFunction() |
| 183 : counters = const { Metric.functions: 1}, entries = const {}, uri = null; | 176 : counters = const {Metric.functions: 1}, |
| 177 entries = const {}, | |
| 178 uri = null; | |
| 184 | 179 |
| 185 Measurements.reachableFunction([this.uri]) | 180 Measurements.reachableFunction([this.uri]) |
| 186 : counters = { Metric.functions: 1, Metric.reachableFunctions: 1}, | 181 : counters = {Metric.functions: 1, Metric.reachableFunctions: 1}, |
| 187 entries = {}; | 182 entries = {}; |
| 188 | 183 |
| 189 /// Record [metric] was seen. The optional [begin] and [end] offsets are | 184 /// Record [metric] was seen. The optional [begin] and [end] offsets are |
| 190 /// included for metrics that correspond to a source range. Intended to be | 185 /// included for metrics that correspond to a source range. Intended to be |
| 191 /// used by `StatsBuilder`. | 186 /// used by `StatsBuilder`. |
| 192 record(Metric metric, [int begin, int end]) { | 187 record(Metric metric, [int begin, int end]) { |
| 193 if (begin != null && end != null) { | 188 if (begin != null && end != null) { |
| 194 assert(uri != null); | 189 assert(uri != null); |
| 195 entries.putIfAbsent(metric, () => []).add(new Entry(begin, end)); | 190 entries.putIfAbsent(metric, () => []).add(new Entry(begin, end)); |
| 196 } | 191 } |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 221 /// submetric. | 216 /// submetric. |
| 222 bool checkInvariant(GroupedMetric key) { | 217 bool checkInvariant(GroupedMetric key) { |
| 223 int total = counters[key] ?? 0; | 218 int total = counters[key] ?? 0; |
| 224 int submetricTotal = 0; | 219 int submetricTotal = 0; |
| 225 for (var metric in key.submetrics) { | 220 for (var metric in key.submetrics) { |
| 226 var n = counters[metric]; | 221 var n = counters[metric]; |
| 227 if (n != null) submetricTotal += n; | 222 if (n != null) submetricTotal += n; |
| 228 } | 223 } |
| 229 return total == submetricTotal; | 224 return total == submetricTotal; |
| 230 } | 225 } |
| 231 | |
| 232 Map toJson() { | |
| 233 var jsonEntries = <String, List<Map>>{}; | |
| 234 entries.forEach((metric, values) { | |
| 235 jsonEntries[metric.toJson()] = | |
| 236 values.expand((e) => [e.begin, e.end]).toList(); | |
| 237 }); | |
| 238 var json = {'entries': jsonEntries}; | |
| 239 // TODO(sigmund): encode uri as an offset of the URIs available in the parts | |
| 240 // of the library info. | |
| 241 if (uri != null) json['sourceFile'] = '$uri'; | |
| 242 if (counters[Metric.functions] != null) { | |
| 243 json[Metric.functions.toJson()] = counters[Metric.functions]; | |
| 244 } | |
| 245 if (counters[Metric.reachableFunctions] != null) { | |
| 246 json[Metric.reachableFunctions.toJson()] = | |
| 247 counters[Metric.reachableFunctions]; | |
| 248 } | |
| 249 return json; | |
| 250 } | |
| 251 } | 226 } |
| OLD | NEW |