From 1bf4b0ce2f1904a13c604fdd9d824f18d4373ce8 Mon Sep 17 00:00:00 2001 From: Konstantin Shcheglov Date: Tue, 6 Apr 2021 21:10:33 +0000 Subject: [PATCH] Migrate benchmark/integration/ R=brianwilkerson@google.com Change-Id: I0dccc13831ec5aed82d33ee52ffeae1ad38c5b98 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/194109 Reviewed-by: Brian Wilkerson Commit-Queue: Konstantin Shcheglov --- .../benchmark/integration/driver.dart | 27 ++++---- .../integration/input_converter.dart | 49 +++++++-------- .../instrumentation_input_converter.dart | 9 ++- .../benchmark/integration/local_runner.dart | 4 +- .../integration/log_file_input_converter.dart | 4 +- .../benchmark/integration/main.dart | 62 +++++++++---------- .../benchmark/integration/operation.dart | 53 ++++++++-------- 7 files changed, 100 insertions(+), 108 deletions(-) diff --git a/pkg/analysis_server/benchmark/integration/driver.dart b/pkg/analysis_server/benchmark/integration/driver.dart index 6e831aa0ff98..9f40d740712e 100644 --- a/pkg/analysis_server/benchmark/integration/driver.dart +++ b/pkg/analysis_server/benchmark/integration/driver.dart @@ -2,8 +2,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart = 2.9 - import 'dart:async'; import 'dart:math' show max, sqrt; @@ -42,13 +40,13 @@ class Driver extends IntegrationTestMixin { final Logger logger = Logger('Driver'); /// The diagnostic port for Analysis Server or `null` if none. - final int diagnosticPort; + final int? diagnosticPort; /// A flag indicating whether the server is running. bool running = false; @override - Server server; + late Server server; /// The results collected while running analysis server. final Results results = Results(); @@ -65,7 +63,7 @@ class Driver extends IntegrationTestMixin { /// Perform the given operation. /// Return a [Future] that completes when the next operation can be performed, /// or `null` if the next operation can be performed immediately - Future perform(Operation op) { + Future? perform(Operation op) { return op.perform(this); } @@ -75,7 +73,7 @@ class Driver extends IntegrationTestMixin { /// normal (non-error) response, the future will be completed with the /// 'result' field from the response. If the server acknowledges the command /// with an error response, the future will be completed with an error. - Future> send( + Future?> send( String method, Map params) { return server.send(method, params); } @@ -206,14 +204,17 @@ class Results { print(''); print('=================================================================='); print(''); - var keys = measurements.keys.toList()..sort(); - var keyLen = keys.fold(0, (int len, String key) => max(len, key.length)); + var sortedEntries = measurements.entries.toList(); + sortedEntries.sort((a, b) => a.key.compareTo(b.key)); + var keyLen = sortedEntries + .map((e) => e.key) + .fold(0, (int len, String key) => max(len, key.length)); _printGroupHeader('Request/Response', keyLen); var totalCount = 0; var totalErrorCount = 0; var totalUnexpectedResultCount = 0; - for (var tag in keys) { - var m = measurements[tag]; + for (var entry in sortedEntries) { + var m = entry.value; if (!m.notification) { m.printSummary(keyLen); totalCount += m.count; @@ -225,8 +226,8 @@ class Results { keyLen, totalCount, totalErrorCount, totalUnexpectedResultCount); print(''); _printGroupHeader('Notifications', keyLen); - for (var tag in keys) { - var m = measurements[tag]; + for (var entry in sortedEntries) { + var m = entry.value; if (m.notification) { m.printSummary(keyLen); } @@ -252,7 +253,7 @@ class Results { } void recordUnexpectedResults(String tag) { - measurements[tag].recordUnexpectedResults(); + measurements[tag]!.recordUnexpectedResults(); } void _printGroupHeader(String groupName, int keyLen) { diff --git a/pkg/analysis_server/benchmark/integration/input_converter.dart b/pkg/analysis_server/benchmark/integration/input_converter.dart index e128456bac57..0f8691978b2f 100644 --- a/pkg/analysis_server/benchmark/integration/input_converter.dart +++ b/pkg/analysis_server/benchmark/integration/input_converter.dart @@ -2,8 +2,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart = 2.9 - import 'dart:async'; import 'dart:convert'; import 'dart:io'; @@ -20,14 +18,14 @@ import 'log_file_input_converter.dart'; import 'operation.dart'; /// Common input converter superclass for sharing implementation. -abstract class CommonInputConverter extends Converter { +abstract class CommonInputConverter extends Converter { static final ERROR_PREFIX = 'Server responded with an error: '; final Logger logger = Logger('InstrumentationInputConverter'); final Set eventsSeen = {}; /// A mapping from request/response id to request json /// for those requests for which a response has not been processed. - final Map requestMap = {}; + final Map requestMap = {}; /// A mapping from request/response id to a completer /// for those requests for which a response has not been processed. @@ -37,7 +35,7 @@ abstract class CommonInputConverter extends Converter { /// A mapping from request/response id to the actual response result /// for those responses that have not been processed. - final Map responseMap = {}; + final Map responseMap = {}; /// A mapping of current overlay content /// parallel to what is in the analysis server @@ -58,16 +56,18 @@ abstract class CommonInputConverter extends Converter { CommonInputConverter(this.tmpSrcDirPath, this.srcPathMap); - Map asMap(dynamic value) => value as Map; + Map asMap(dynamic value) => value as Map; + + Map? asMap2(dynamic value) => value as Map?; /// Return an operation for the notification or `null` if none. - Operation convertNotification(Map json) { + Operation? convertNotification(Map json) { String event = json['event']; if (event == SERVER_NOTIFICATION_STATUS) { // {"event":"server.status","params":{"analysis":{"isAnalyzing":false}}} - var params = asMap(json['params']); + var params = asMap2(json['params']); if (params != null) { - var analysis = asMap(params['analysis']); + var analysis = asMap2(params['analysis']); if (analysis != null && analysis['isAnalyzing'] == false) { return WaitForAnalysisCompleteOperation(); } @@ -84,23 +84,20 @@ abstract class CommonInputConverter extends Converter { } /// Return an operation for the request or `null` if none. - Operation convertRequest(Map origJson) { + Operation convertRequest(Map origJson) { var json = asMap(translateSrcPaths(origJson)); - requestMap[json['id']] = json; - String method = json['method']; + requestMap[json['id'] as String] = json; + var method = json['method'] as String; // Sanity check operations that modify source // to ensure that the operation is on source in temp space if (method == ANALYSIS_REQUEST_UPDATE_CONTENT) { // Track overlays in parallel with the analysis server // so that when an overlay is removed, the file can be updated on disk - var request = Request.fromJson(json); + var request = Request.fromJson(json)!; var params = AnalysisUpdateContentParams.fromRequest(request); params.files.forEach((String filePath, change) { if (change is AddContentOverlay) { var content = change.content; - if (content == null) { - throw 'expected new overlay content\n$json'; - } overlays[filePath] = content; } else if (change is ChangeContentOverlay) { var content = overlays[filePath]; @@ -172,8 +169,9 @@ abstract class CommonInputConverter extends Converter { void processErrorResponse(String id, exception) { var result = exception; if (exception is UnimplementedError) { - if (exception.message.startsWith(ERROR_PREFIX)) { - result = json.decode(exception.message.substring(ERROR_PREFIX.length)); + var message = exception.message; + if (message!.startsWith(ERROR_PREFIX)) { + result = json.decode(message.substring(ERROR_PREFIX.length)); } } processResponseResult(id, result); @@ -186,7 +184,7 @@ abstract class CommonInputConverter extends Converter { /// Return a future that completes when the response is received /// or `null` if the response has already been received /// and the completer completed. - Future processExpectedResponse(String id, Completer completer) { + Future? processExpectedResponse(String id, Completer completer) { if (responseMap.containsKey(id)) { logger.log(Level.INFO, 'processing cached response $id'); completer.complete(responseMap.remove(id)); @@ -228,7 +226,7 @@ abstract class CommonInputConverter extends Converter { return result; } if (json is Map) { - var result = {}; + var result = {}; json.forEach((origKey, value) { result[translateSrcPaths(origKey)] = translateSrcPaths(value); }); @@ -241,7 +239,7 @@ abstract class CommonInputConverter extends Converter { /// [InputConverter] converts an input stream /// into a series of operations to be sent to the analysis server. /// The input stream can be either an instrumentation or log file. -class InputConverter extends Converter { +class InputConverter extends Converter { final Logger logger = Logger('InputConverter'); /// A mapping of source path prefixes @@ -259,7 +257,7 @@ class InputConverter extends Converter { /// The underlying converter used to translate lines into operations /// or `null` if it has not yet been determined. - Converter converter; + Converter? converter; /// [active] is `true` if converting lines to operations /// or `false` if an exception has occurred. @@ -268,10 +266,11 @@ class InputConverter extends Converter { InputConverter(this.tmpSrcDirPath, this.srcPathMap); @override - Operation convert(String line) { + Operation? convert(String line) { if (!active) { return null; } + var converter = this.converter; if (converter != null) { try { return converter.convert(line); @@ -335,8 +334,8 @@ class PathMapEntry { } class _InputSink extends ChunkedConversionSink { - final Converter converter; - final Sink outSink; + final Converter converter; + final Sink outSink; _InputSink(this.converter, this.outSink); diff --git a/pkg/analysis_server/benchmark/integration/instrumentation_input_converter.dart b/pkg/analysis_server/benchmark/integration/instrumentation_input_converter.dart index 2cd878362f91..037c9b0233dd 100644 --- a/pkg/analysis_server/benchmark/integration/instrumentation_input_converter.dart +++ b/pkg/analysis_server/benchmark/integration/instrumentation_input_converter.dart @@ -2,8 +2,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart = 2.9 - import 'dart:convert'; import 'package:analyzer/exception/exception.dart'; @@ -23,17 +21,18 @@ class InstrumentationInputConverter extends CommonInputConverter { /// [readBuffer] holds the contents of the file being read from disk /// as recorded in the instrumentation log /// or `null` if not converting a "Read" entry. - StringBuffer readBuffer; + StringBuffer? readBuffer; InstrumentationInputConverter(String tmpSrcDirPath, PathMap srcPathMap) : super(tmpSrcDirPath, srcPathMap); @override - Operation convert(String line) { + Operation? convert(String line) { List fields; try { fields = _parseFields(line); if (fields.length < 2) { + var readBuffer = this.readBuffer; if (readBuffer != null) { readBuffer.writeln(fields.length == 1 ? fields[0] : ''); return null; @@ -78,7 +77,7 @@ class InstrumentationInputConverter extends CommonInputConverter { return null; } - Map decodeJson(String line, String text) { + Map decodeJson(String line, String text) { try { return asMap(json.decode(text)); } catch (e, s) { diff --git a/pkg/analysis_server/benchmark/integration/local_runner.dart b/pkg/analysis_server/benchmark/integration/local_runner.dart index e8353b22ebd2..f8a987ad74ed 100644 --- a/pkg/analysis_server/benchmark/integration/local_runner.dart +++ b/pkg/analysis_server/benchmark/integration/local_runner.dart @@ -2,8 +2,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart = 2.9 - import 'dart:io'; import 'package:path/path.dart'; @@ -77,7 +75,7 @@ void main(List args) { } /// Print help and exit -void printHelp([String errMsg]) { +void printHelp([String? errMsg]) { if (errMsg != null) { print(''); print('Error: $errMsg'); diff --git a/pkg/analysis_server/benchmark/integration/log_file_input_converter.dart b/pkg/analysis_server/benchmark/integration/log_file_input_converter.dart index 238a1fa7a5b1..bd87c707111f 100644 --- a/pkg/analysis_server/benchmark/integration/log_file_input_converter.dart +++ b/pkg/analysis_server/benchmark/integration/log_file_input_converter.dart @@ -2,8 +2,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart = 2.9 - import 'dart:convert'; import 'package:analyzer/exception/exception.dart'; @@ -25,7 +23,7 @@ class LogFileInputConverter extends CommonInputConverter { : super(tmpSrcDirPath, srcPathMap); @override - Operation convert(String line) { + Operation? convert(String line) { try { var timeStampString = _parseTimeStamp(line); var data = line.substring(timeStampString.length); diff --git a/pkg/analysis_server/benchmark/integration/main.dart b/pkg/analysis_server/benchmark/integration/main.dart index c1c9911e5ab9..8f0a438bdb8a 100644 --- a/pkg/analysis_server/benchmark/integration/main.dart +++ b/pkg/analysis_server/benchmark/integration/main.dart @@ -2,8 +2,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart = 2.9 - import 'dart:async'; import 'dart:convert'; import 'dart:io'; @@ -26,9 +24,9 @@ void main(List rawArgs) { var driver = Driver(diagnosticPort: args.diagnosticPort); var stream = openInput(args); - StreamSubscription subscription; - subscription = stream.listen((Operation op) { - var future = driver.perform(op); + late StreamSubscription subscription; + subscription = stream.listen((Operation? op) { + var future = driver.perform(op!); if (future != null) { logger.log(Level.FINE, 'pausing operations for ${op.runtimeType}'); subscription.pause(future.then((_) { @@ -63,17 +61,15 @@ const TMP_SRC_DIR_OPTION = 'tmpSrcDir'; const VERBOSE_CMDLINE_OPTION = 'verbose'; const VERY_VERBOSE_CMDLINE_OPTION = 'vv'; -ArgParser _argParser; - -ArgParser get argParser { - _argParser = ArgParser(); +late final ArgParser argParser = () { + var argParser = ArgParser(); - _argParser.addOption(INPUT_CMDLINE_OPTION, + argParser.addOption(INPUT_CMDLINE_OPTION, abbr: 'i', help: '\n' 'The input file specifying how this client should interact with the server.\n' 'If the input file name is "stdin", then the instructions are read from standard input.'); - _argParser.addMultiOption(MAP_OPTION, + argParser.addMultiOption(MAP_OPTION, abbr: 'm', splitCommas: false, help: ',\n' @@ -82,26 +78,26 @@ ArgParser get argParser { 'to the target source directory used during performance testing.\n' 'Multiple mappings can be specified.\n' 'WARNING: The contents of the target directory will be modified'); - _argParser.addOption(TMP_SRC_DIR_OPTION, + argParser.addOption(TMP_SRC_DIR_OPTION, abbr: 't', help: '\n' 'The temporary directory containing source used during performance measurement.\n' 'WARNING: The contents of the target directory will be modified'); - _argParser.addOption(DIAGNOSTIC_PORT_OPTION, + argParser.addOption(DIAGNOSTIC_PORT_OPTION, abbr: 'd', help: 'localhost port on which server will provide diagnostic web pages'); - _argParser.addFlag(VERBOSE_CMDLINE_OPTION, + argParser.addFlag(VERBOSE_CMDLINE_OPTION, abbr: 'v', help: 'Verbose logging', negatable: false); - _argParser.addFlag(VERY_VERBOSE_CMDLINE_OPTION, + argParser.addFlag(VERY_VERBOSE_CMDLINE_OPTION, help: 'Extra verbose logging', negatable: false); - _argParser.addFlag(HELP_CMDLINE_OPTION, + argParser.addFlag(HELP_CMDLINE_OPTION, abbr: 'h', help: 'Print this help information', negatable: false); - return _argParser; -} + return argParser; +}(); /// Open and return the input stream specifying how this client /// should interact with the analysis server. -Stream openInput(PerfArgs args) { +Stream openInput(PerfArgs args) { var logger = Logger('openInput'); Stream> inputRaw; if (args.inputPath == 'stdin') { @@ -137,12 +133,12 @@ PerfArgs parseArgs(List rawArgs) { var showHelp = args[HELP_CMDLINE_OPTION] || args.rest.isNotEmpty; - bool isMissing(key) => args[key] == null || args[key].isEmpty; - - perfArgs.inputPath = args[INPUT_CMDLINE_OPTION]; - if (isMissing(INPUT_CMDLINE_OPTION)) { + var inputArg = args[INPUT_CMDLINE_OPTION]; + if (inputArg is! String || inputArg.isEmpty) { print('missing $INPUT_CMDLINE_OPTION argument'); showHelp = true; + } else { + perfArgs.inputPath = inputArg; } for (String pair in args[MAP_OPTION]) { @@ -157,18 +153,20 @@ PerfArgs parseArgs(List rawArgs) { } } } - print('must specifiy $MAP_OPTION ,'); + print('must specify $MAP_OPTION ,'); showHelp = true; } - perfArgs.tmpSrcDirPath = _withTrailingSeparator(args[TMP_SRC_DIR_OPTION]); - if (isMissing(TMP_SRC_DIR_OPTION)) { + var tmpSrcDirPathArg = args[TMP_SRC_DIR_OPTION]; + if (tmpSrcDirPathArg is! String || tmpSrcDirPathArg.isEmpty) { print('missing $TMP_SRC_DIR_OPTION argument'); showHelp = true; + } else { + perfArgs.tmpSrcDirPath = _withTrailingSeparator(tmpSrcDirPathArg); } - String portText = args[DIAGNOSTIC_PORT_OPTION]; - if (portText != null) { + var portText = args[DIAGNOSTIC_PORT_OPTION]; + if (portText is String) { if (int.tryParse(portText) == null) { print('invalid $DIAGNOSTIC_PORT_OPTION: $portText'); showHelp = true; @@ -202,7 +200,7 @@ void printHelp() { /// Ensure that the given path has a trailing separator String _withTrailingSeparator(String dirPath) { - if (dirPath != null && dirPath.length > 4) { + if (dirPath.length > 4) { if (!dirPath.endsWith(path.separator)) { return '$dirPath${path.separator}'; } @@ -215,7 +213,7 @@ class PerfArgs { /// The file path of the instrumentation or log file /// used to drive performance measurement, /// or 'stdin' if this information should be read from standard input. - String inputPath; + late String inputPath; /// A mapping from the original source directory /// when the instrumentation or log file was generated @@ -224,8 +222,8 @@ class PerfArgs { /// The temporary directory containing source used during performance /// measurement. - String tmpSrcDirPath; + late String tmpSrcDirPath; /// The diagnostic port for Analysis Server or `null` if none. - int diagnosticPort; + int? diagnosticPort; } diff --git a/pkg/analysis_server/benchmark/integration/operation.dart b/pkg/analysis_server/benchmark/integration/operation.dart index eb70f441c972..311e9790714d 100644 --- a/pkg/analysis_server/benchmark/integration/operation.dart +++ b/pkg/analysis_server/benchmark/integration/operation.dart @@ -2,8 +2,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart = 2.9 - import 'dart:async'; import 'package:analysis_server/protocol/protocol_generated.dart'; @@ -15,10 +13,10 @@ import 'input_converter.dart'; /// A [CompletionRequestOperation] tracks response time along with /// the first and last completion notifications. class CompletionRequestOperation extends RequestOperation { - Driver driver; - StreamSubscription subscription; - String notificationId; - Stopwatch stopwatch; + late Driver driver; + late StreamSubscription subscription; + late String notificationId; + late Stopwatch stopwatch; bool firstNotification = true; CompletionRequestOperation( @@ -26,7 +24,7 @@ class CompletionRequestOperation extends RequestOperation { : super(converter, json); @override - Future perform(Driver driver) { + Future? perform(Driver driver) { this.driver = driver; subscription = driver.onCompletionResults.listen(processNotification); return super.perform(driver); @@ -50,8 +48,8 @@ class CompletionRequestOperation extends RequestOperation { @override void processResult( - String id, Map result, Stopwatch stopwatch) { - notificationId = result['id']; + String id, Map result, Stopwatch stopwatch) { + notificationId = result['id'] as String; this.stopwatch = stopwatch; super.processResult(id, result, stopwatch); } @@ -59,7 +57,7 @@ class CompletionRequestOperation extends RequestOperation { /// An [Operation] represents an action such as sending a request to the server. abstract class Operation { - Future perform(Driver driver); + Future? perform(Driver driver); } /// A [RequestOperation] sends a [JSON] request to the server. @@ -70,7 +68,7 @@ class RequestOperation extends Operation { RequestOperation(this.converter, this.json); @override - Future perform(Driver driver) { + Future? perform(Driver driver) { var stopwatch = Stopwatch(); String originalId = json['id']; String method = json['method']; @@ -85,11 +83,9 @@ class RequestOperation extends Operation { .log(Level.FINE, 'Response received: $method : $elapsed\n $result'); } - driver - .send(method, converter.asMap(json['params'])) - .then((Map result) { + driver.send(method, converter.asMap(json['params'])).then((result) { recordResult(true, result); - processResult(originalId, result, stopwatch); + processResult(originalId, result!, stopwatch); }).catchError((exception) { recordResult(false, exception); converter.processErrorResponse(originalId, exception); @@ -98,7 +94,7 @@ class RequestOperation extends Operation { } void processResult( - String id, Map result, Stopwatch stopwatch) { + String id, Map result, Stopwatch stopwatch) { converter.processResponseResult(id, result); } } @@ -107,19 +103,20 @@ class RequestOperation extends Operation { class ResponseOperation extends Operation { static final Duration responseTimeout = Duration(seconds: 60); final CommonInputConverter converter; - final Map requestJson; - final Map responseJson; + final Map requestJson; + final Map responseJson; final Completer completer = Completer(); - Driver driver; + late Driver driver; ResponseOperation(this.converter, this.requestJson, this.responseJson) { completer.future.then(_processResult).timeout(responseTimeout); } @override - Future perform(Driver driver) { + Future? perform(Driver driver) { this.driver = driver; - return converter.processExpectedResponse(responseJson['id'], completer); + var id = responseJson['id'] as String; + return converter.processExpectedResponse(id, completer); } bool _equal(expectedResult, actualResult) { @@ -161,7 +158,8 @@ class ResponseOperation extends Operation { 'expected result:${format(expectedResult)}\n' 'expected error:${format(expectedError)}\n' 'but received:${format(actualResult)}'; - driver.results.recordUnexpectedResults(requestJson['method']); + var method = requestJson['method'] as String; + driver.results.recordUnexpectedResults(method); converter.logOverlayContent(); if (expectedError == null) { converter.logger.log(Level.SEVERE, message); @@ -184,13 +182,14 @@ class WaitForAnalysisCompleteOperation extends Operation { Future perform(Driver driver) { var start = DateTime.now(); driver.logger.log(Level.FINE, 'waiting for analysis to complete'); - StreamSubscription subscription; - Timer timer; + late StreamSubscription subscription; + late Timer timer; var completer = Completer(); var isAnalyzing = false; subscription = driver.onServerStatus.listen((ServerStatusParams params) { - if (params.analysis != null) { - if (params.analysis.isAnalyzing) { + var analysisStatus = params.analysis; + if (analysisStatus != null) { + if (analysisStatus.isAnalyzing) { isAnalyzing = true; } else { subscription.cancel(); @@ -214,7 +213,7 @@ class WaitForAnalysisCompleteOperation extends Operation { } // Timeout if no communication received within the last 60 seconds. var currentTime = driver.server.currentElapseTime; - var lastTime = driver.server.lastCommunicationTime; + var lastTime = driver.server.lastCommunicationTime!; if (currentTime - lastTime > 60) { subscription.cancel(); timer.cancel();