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

Side by Side Diff: pkg/analysis_server/test/performance/driver.dart

Issue 1219023006: move performance measurement to benchmark/integration (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: merge Created 5 years, 5 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 library server.driver;
6
7 import 'dart:async';
8 import 'dart:math' show max, sqrt;
9
10 import 'package:analyzer/src/generated/engine.dart' as engine;
11 import 'package:logging/logging.dart';
12
13 import '../integration/integration_test_methods.dart';
14 import '../integration/integration_tests.dart';
15 import 'operation.dart';
16
17 final SPACE = ' '.codeUnitAt(0);
18
19 void _printColumn(StringBuffer sb, String text, int keyLen,
20 {bool rightJustified: false}) {
21 if (!rightJustified) {
22 sb.write(text);
23 sb.write(',');
24 }
25 for (int i = text.length; i < keyLen; ++i) {
26 sb.writeCharCode(SPACE);
27 }
28 if (rightJustified) {
29 sb.write(text);
30 sb.write(',');
31 }
32 sb.writeCharCode(SPACE);
33 }
34
35 /**
36 * [Driver] launches and manages an instance of analysis server,
37 * reads a stream of operations, sends requests to analysis server
38 * based upon those operations, and evaluates the results.
39 */
40 class Driver extends IntegrationTestMixin {
41 /**
42 * The amount of time to give the server to respond to a shutdown request
43 * before forcibly terminating it.
44 */
45 static const Duration SHUTDOWN_TIMEOUT = const Duration(seconds: 5);
46
47 final Logger logger;
48
49 /**
50 * A flag indicating whether the server is running.
51 */
52 bool running = false;
53
54 @override
55 Server server;
56
57 /**
58 * The results collected while running analysis server.
59 */
60 final Results results = new Results();
61
62 /**
63 * The [Completer] for [runComplete].
64 */
65 Completer<Results> _runCompleter = new Completer<Results>();
66
67 Driver(this.logger);
68
69 /**
70 * Return a [Future] that completes with the [Results] of running
71 * the analysis server once all operations have been performed.
72 */
73 Future<Results> get runComplete => _runCompleter.future;
74
75 /**
76 * Perform the given operation.
77 * Return a [Future] that completes when the next operation can be performed,
78 * or `null` if the next operation can be performed immediately
79 */
80 Future perform(Operation op) {
81 return op.perform(this);
82 }
83
84 /**
85 * Send a command to the server. An 'id' will be automatically assigned.
86 * The returned [Future] will be completed when the server acknowledges the
87 * command with a response. If the server acknowledges the command with a
88 * normal (non-error) response, the future will be completed with the 'result'
89 * field from the response. If the server acknowledges the command with an
90 * error response, the future will be completed with an error.
91 */
92 Future send(String method, Map<String, dynamic> params) {
93 return server.send(method, params);
94 }
95
96 /**
97 * Launch the analysis server.
98 * Return a [Future] that completes when analysis server has started.
99 */
100 Future startServer({int diagnosticPort}) async {
101 logger.log(Level.FINE, 'starting server');
102 initializeInttestMixin();
103 server = new Server();
104 Completer serverConnected = new Completer();
105 onServerConnected.listen((_) {
106 logger.log(Level.FINE, 'connected to server');
107 serverConnected.complete();
108 });
109 running = true;
110 return server
111 .start(diagnosticPort: diagnosticPort /*profileServer: true*/)
112 .then((params) {
113 server.listenToOutput(dispatchNotification);
114 server.exitCode.then((_) {
115 logger.log(Level.FINE, 'server stopped');
116 running = false;
117 _resultsReady();
118 });
119 return serverConnected.future;
120 });
121 }
122
123 /**
124 * Shutdown the analysis server if it is running.
125 */
126 Future stopServer([Duration timeout = SHUTDOWN_TIMEOUT]) async {
127 if (running) {
128 logger.log(Level.FINE, 'requesting server shutdown');
129 // Give the server a short time to comply with the shutdown request; if it
130 // doesn't exit, then forcibly terminate it.
131 sendServerShutdown();
132 await server.exitCode.timeout(timeout, onTimeout: () {
133 return server.kill();
134 });
135 }
136 _resultsReady();
137 }
138
139 /**
140 * If not already complete, signal the completer with the collected results.
141 */
142 void _resultsReady() {
143 if (!_runCompleter.isCompleted) {
144 _runCompleter.complete(results);
145 }
146 }
147 }
148
149 /**
150 * [Measurement] tracks elapsed time for a given operation.
151 */
152 class Measurement {
153 final String tag;
154 final bool notification;
155 final List<Duration> elapsedTimes = new List<Duration>();
156 int errorCount = 0;
157 int unexpectedResultCount = 0;
158
159 Measurement(this.tag, this.notification);
160
161 int get count => elapsedTimes.length;
162
163 void printSummary(int keyLen) {
164 int count = 0;
165 Duration maxTime = elapsedTimes[0];
166 Duration minTime = elapsedTimes[0];
167 int totalTimeMicros = 0;
168 for (Duration elapsed in elapsedTimes) {
169 ++count;
170 int timeMicros = elapsed.inMicroseconds;
171 maxTime = maxTime.compareTo(elapsed) > 0 ? maxTime : elapsed;
172 minTime = minTime.compareTo(elapsed) < 0 ? minTime : elapsed;
173 totalTimeMicros += timeMicros;
174 }
175 int meanTime = (totalTimeMicros / count).round();
176 List<Duration> sorted = elapsedTimes.toList()..sort();
177 Duration time90th = sorted[(sorted.length * 0.90).round() - 1];
178 Duration time99th = sorted[(sorted.length * 0.99).round() - 1];
179 int differenceFromMeanSquared = 0;
180 for (Duration elapsed in elapsedTimes) {
181 int timeMicros = elapsed.inMicroseconds;
182 int differenceFromMean = timeMicros - meanTime;
183 differenceFromMeanSquared += differenceFromMean * differenceFromMean;
184 }
185 double variance = differenceFromMeanSquared / count;
186 int standardDeviation = sqrt(variance).round();
187
188 StringBuffer sb = new StringBuffer();
189 _printColumn(sb, tag, keyLen);
190 _printColumn(sb, count.toString(), 6, rightJustified: true);
191 _printColumn(sb, errorCount.toString(), 6, rightJustified: true);
192 _printColumn(sb, unexpectedResultCount.toString(), 6, rightJustified: true);
193 _printDuration(sb, new Duration(microseconds: meanTime));
194 _printDuration(sb, time90th);
195 _printDuration(sb, time99th);
196 _printColumn(sb, standardDeviation.toString(), 15, rightJustified: true);
197 _printDuration(sb, minTime);
198 _printDuration(sb, maxTime);
199 _printDuration(sb, new Duration(microseconds: totalTimeMicros));
200 print(sb.toString());
201 }
202
203 void record(bool success, Duration elapsed) {
204 if (!success) {
205 ++errorCount;
206 }
207 elapsedTimes.add(elapsed);
208 }
209
210 void recordUnexpectedResults() {
211 ++unexpectedResultCount;
212 }
213
214 void _printDuration(StringBuffer sb, Duration duration) {
215 sb.write(' ');
216 sb.write(duration);
217 sb.write(',');
218 }
219 }
220
221 /**
222 * [Results] contains information gathered by [Driver]
223 * while running the analysis server
224 */
225 class Results {
226 Map<String, Measurement> measurements = new Map<String, Measurement>();
227
228 /**
229 * Display results on stdout.
230 */
231 void printResults() {
232 print('');
233 print('==================================================================');
234 if (engine.AnalysisEngine.instance.useTaskModel) {
235 print('New task model');
236 } else {
237 print('Old task model');
238 }
239 print('');
240 List<String> keys = measurements.keys.toList()..sort();
241 int keyLen = keys.fold(0, (int len, String key) => max(len, key.length));
242 _printGroupHeader('Request/Response', keyLen);
243 int totalCount = 0;
244 int totalErrorCount = 0;
245 int totalUnexpectedResultCount = 0;
246 for (String tag in keys) {
247 Measurement m = measurements[tag];
248 if (!m.notification) {
249 m.printSummary(keyLen);
250 totalCount += m.count;
251 totalErrorCount += m.errorCount;
252 totalUnexpectedResultCount += m.unexpectedResultCount;
253 }
254 }
255 _printTotals(
256 keyLen, totalCount, totalErrorCount, totalUnexpectedResultCount);
257 print('');
258 _printGroupHeader('Notifications', keyLen);
259 for (String tag in keys) {
260 Measurement m = measurements[tag];
261 if (m.notification) {
262 m.printSummary(keyLen);
263 }
264 }
265 /// TODO(danrubel) *** print warnings if driver caches are not empty ****
266 print('');
267 print(
268 '(1) uxr = UneXpected Results, or responses received from the server');
269 print(
270 ' that do not match the recorded response for that request.');
271 }
272
273 /**
274 * Record the elapsed time for the given operation.
275 */
276 void record(String tag, Duration elapsed,
277 {bool notification: false, bool success: true}) {
278 Measurement measurement = measurements[tag];
279 if (measurement == null) {
280 measurement = new Measurement(tag, notification);
281 measurements[tag] = measurement;
282 }
283 measurement.record(success, elapsed);
284 }
285
286 void recordUnexpectedResults(String tag) {
287 measurements[tag].recordUnexpectedResults();
288 }
289
290 void _printGroupHeader(String groupName, int keyLen) {
291 StringBuffer sb = new StringBuffer();
292 _printColumn(sb, groupName, keyLen);
293 _printColumn(sb, 'count', 6, rightJustified: true);
294 _printColumn(sb, 'error', 6, rightJustified: true);
295 _printColumn(sb, 'uxr(1)', 6, rightJustified: true);
296 sb.write(' ');
297 _printColumn(sb, 'mean', 15);
298 _printColumn(sb, '90th', 15);
299 _printColumn(sb, '99th', 15);
300 _printColumn(sb, 'std-dev', 15);
301 _printColumn(sb, 'minimum', 15);
302 _printColumn(sb, 'maximum', 15);
303 _printColumn(sb, 'total', 15);
304 print(sb.toString());
305 }
306
307 void _printTotals(int keyLen, int totalCount, int totalErrorCount,
308 int totalUnexpectedResultCount) {
309 StringBuffer sb = new StringBuffer();
310 _printColumn(sb, 'Totals', keyLen);
311 _printColumn(sb, totalCount.toString(), 6, rightJustified: true);
312 _printColumn(sb, totalErrorCount.toString(), 6, rightJustified: true);
313 _printColumn(sb, totalUnexpectedResultCount.toString(), 6,
314 rightJustified: true);
315 print(sb.toString());
316 }
317 }
OLDNEW
« no previous file with comments | « pkg/analysis_server/test/integration/integration_tests.dart ('k') | pkg/analysis_server/test/performance/input_converter.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698