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 |