Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(48)

Side by Side Diff: lib/src/measurements.dart

Issue 1372333002: Add measurements and send-metrics to dart2js's info. (Closed) Base URL: git@github.com:dart-lang/dart2js_info.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 /// Measurements collected about individual functions. Currently we compute
6 /// data about "sends", to classify whether we know the target or not.
7 library dart2js_info.src.measurements;
8
9 /// Top-level set of metrics
10 const List<Metric> _topLevelMetrics = const [
11 Metric.functions,
12 Metric.send,
13 ];
14
15 /// 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
17 /// details on the subtrees.
18 visitAllMetrics(f) {
19 var parentsStack = [];
20 helper(Metric m) {
21 f(m, parentsStack);
22 if (m is GroupedMetric) {
23 parentsStack.add(m);
24 m.submetrics.forEach(helper);
25 parentsStack.removeLast();
26 }
27 }
28 _topLevelMetrics.forEach(helper);
29 }
30
31 /// A metric we intend to measure.
32 class Metric {
33 /// Name for the metric.
34 final String name;
35
36 const Metric(this.name);
37
38 String toString() => name;
39
40 /// Total functions in a library/package/program. Parent of
41 /// [reachableFunction].
42 static const Metric functions = const GroupedMetric('functions', const [
43 reachableFunctions,
44 ]);
45
46 /// Subset of the functions that are reachable.
47 static const Metric reachableFunctions = const Metric('reachable functions');
48
49 /// Parent of all send metrics. We classify sends as follows:
50 ///
51 /// sends
52 /// |- monomorphic
53 /// | |- static (top-levels, statics)
54 /// | |- super
55 /// | |- local (access to a local var, call local function)
56 /// | |- constructor (like factory ctros)
57 /// | |- type variable (reading a type variable)
58 /// | |- nsm (known no such method exception)
59 /// | |- single-nsm-call (known no such method call, single target)
60 /// | |- instance (non-interceptor, only one possible target)
61 /// | '- interceptor (interceptor, known)
62 /// |
63 /// '- polymorphic
64 /// |- multi-nsm (known to be nSM, but not sure if error, or call, or
65 /// which call)
66 /// |- virtual (traditional virtual call, polymorphic equivalent of
67 /// | `instance`, no-interceptor)
68 /// |- multi-interceptor (1 of n possible interceptors)
69 /// '- dynamic (any combination of the above)
70 ///
71 static const Metric send = const GroupedMetric('send', const [
72 monomorphicSend,
73 polymorphicSend,
74 ]);
75
76 /// Parent of monomorphic sends, see [send] for details.
77 static const Metric monomorphicSend = const GroupedMetric('monomorphic',
78 const [
79 staticSend,
80 superSend,
81 localSend,
82 constructorSend,
83 typeVariableSend,
84 nsmErrorSend,
85 singleNsmCallSend,
86 instanceSend,
87 interceptorSend,
88 ]);
89
90 /// Metric for static calls, see [send] for details.
91 static const Metric staticSend = const Metric('static');
92
93 /// Metric for super calls, see [send] for details.
94 static const Metric superSend = const Metric('super');
95
96 /// Metric for local variable sends, see [send] for details.
97 static const Metric localSend = const Metric('local');
98
99 /// Metric for constructor sends, see [send] for details.
100 static const Metric constructorSend = const Metric('constructor');
101
102 /// Metric for type-variable sends, see [send] for details.
103 // TODO(sigmund): delete? is mainly associated with compile-time errors
104 static const Metric typeVariableSend = const Metric('type variable');
105
106 /// Metric for no-such-method errors, see [send] for details.
107 static const Metric nsmErrorSend = const Metric('nSM error');
108
109 /// Metric for calls to noSuchMethod methods with a known target, see [send]
110 /// for details.
111 static const Metric singleNsmCallSend = const Metric('nSM call single');
112
113 /// Metric for calls to a precisely known instance method, see [send] for
114 /// details.
115 static const Metric instanceSend = const Metric('instance');
116
117 /// Metric for calls to a precisely known interceptor method, see [send] for
118 /// details.
119 static const Metric interceptorSend = const Metric('interceptor');
120
121 /// Parent of polymorphic sends, see [send] for details.
122 static const Metric polymorphicSend = const GroupedMetric('polymorphic',
123 const [
124 multiNsmCallSend,
125 virtualSend,
126 multiInterceptorSend,
127 dynamicSend,
128 ]);
129
130 /// Metric for calls to noSuchMethod methods with more than one possible
131 /// target, see [send] for details.
132 static const Metric multiNsmCallSend = const Metric('nSM call multi');
133
134 /// Metric for calls that are dispatched virtually ar runtime, see [send] for
135 /// details.
136 static const Metric virtualSend = const Metric('virtual');
137
138 /// Metyric for calls to more than one possible interceptor, see [send] for
139 /// details.
140 static const Metric multiInterceptorSend = const Metric('interceptor multi');
141
142 /// Metyric for dynamic calls for which we know nothing about the target
143 /// method. See [send] for details.
144 static const Metric dynamicSend = const Metric('dynamic');
145
146 String toJson() => name;
147 static Map<String, Metric> _nameToMetricMap = () {
148 var res = {};
149 visitAllMetrics((m, _) => res[m.name] = m);
150 return res;
151 }();
152
153 static Metric fromJson(String name) => _nameToMetricMap[name];
154 }
155
156 /// A metric that is subdivided in smaller metrics.
157 class GroupedMetric extends Metric {
158 final List<Metric> submetrics;
159
160 const GroupedMetric(String name, this.submetrics) : super(name);
161 }
162
163 /// A measurement entry (practically a source-span location where the
164 /// measurement was seen).
165 class Entry {
166 final int begin;
167 final int end;
168 Entry(this.begin, this.end);
169 }
170
171 /// A collection of data points for each metric. Used to summarize a single
172 /// function, a library, a package, or an entire program.
173 class Measurements {
174 final Uri uri;
175 final Map<Metric, List<Entry>> entries;
176 final Map<Metric, int> counters;
177
178 Measurements([this.uri])
179 : entries = <Metric, List<Entry>>{},
180 counters = <Metric, int>{};
181
182 const Measurements.unreachableFunction()
183 : counters = const { Metric.functions: 1}, entries = const {}, uri = null;
184
185 Measurements.reachableFunction([this.uri])
186 : counters = { Metric.functions: 1, Metric.reachableFunctions: 1},
187 entries = {};
188
189 /// Record [metric] was seen. The optional [begin] and [end] offsets are
190 /// included for metrics that correspond to a source range. Intended to be
191 /// used by `StatsBuilder`.
192 record(Metric metric, [int begin, int end]) {
193 if (begin != null && end != null) {
194 assert(uri != null);
195 entries.putIfAbsent(metric, () => []).add(new Entry(begin, end));
196 }
197 counters.putIfAbsent(metric, () => 0);
198 counters[metric]++;
199 }
200
201 /// Removes a previously added entry. Intended only to be used by
202 /// `StatsBuilder`. Internally `StatsBuilder` computes redundant information
203 /// in order to check for coverage and validate invariants with
204 /// [checkInvariant]. This is used to adjust some of the redundant
205 /// information.
206 popLast(Metric metric) {
207 assert(entries[metric] != null && entries[metric].isNotEmpty);
208 entries[metric].removeLast();
209 counters[metric]--;
210 }
211
212 /// Add the counters from [other] into this set of measurements.
213 addFrom(Measurements other) {
214 other.counters.forEach((metric, value) {
215 var current = counters[metric];
216 counters[metric] = current == null ? value : current + value;
217 });
218 }
219
220 /// Check that every grouped metric totals the individual counts of it's
221 /// submetric.
222 bool checkInvariant(GroupedMetric key) {
223 int total = counters[key] ?? 0;
224 int submetricTotal = 0;
225 for (var metric in key.submetrics) {
226 var n = counters[metric];
227 if (n != null) submetricTotal += n;
228 }
229 return total == submetricTotal;
230 }
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 }
OLDNEW
« no previous file with comments | « lib/info.dart ('k') | lib/src/string_edit_buffer.dart » ('j') | lib/src/table.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698