| 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 library server.performance; | 5 library server.performance; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:convert'; | 8 import 'dart:convert'; |
| 9 import 'dart:io'; | 9 import 'dart:io'; |
| 10 | 10 |
| 11 import 'package:args/args.dart'; | 11 import 'package:args/args.dart'; |
| 12 import 'package:logging/logging.dart'; | 12 import 'package:logging/logging.dart'; |
| 13 import 'package:path/path.dart' as path; | 13 import 'package:path/path.dart' as path; |
| 14 | 14 |
| 15 import 'driver.dart'; | 15 import 'driver.dart'; |
| 16 import 'input_converter.dart'; | 16 import 'input_converter.dart'; |
| 17 import 'operation.dart'; | 17 import 'operation.dart'; |
| 18 | 18 |
| 19 /** | 19 /** |
| 20 * Launch and interact with the analysis server. | 20 * Launch and interact with the analysis server. |
| 21 */ | 21 */ |
| 22 main(List<String> rawArgs) { | 22 main(List<String> rawArgs) { |
| 23 Logger logger = new Logger('Performance Measurement Client'); | 23 Logger logger = new Logger('Performance Measurement Client'); |
| 24 logger.onRecord.listen((LogRecord rec) { | 24 logger.onRecord.listen((LogRecord rec) { |
| 25 print(rec.message); | 25 print(rec.message); |
| 26 }); | 26 }); |
| 27 PerfArgs args = parseArgs(rawArgs); | 27 PerfArgs args = parseArgs(rawArgs); |
| 28 | 28 |
| 29 Driver driver = new Driver(logger); | 29 Driver driver = new Driver( |
| 30 diagnosticPort: args.diagnosticPort, newTaskModel: args.newTaskModel); |
| 30 Stream<Operation> stream = openInput(args); | 31 Stream<Operation> stream = openInput(args); |
| 31 StreamSubscription<Operation> subscription; | 32 StreamSubscription<Operation> subscription; |
| 32 subscription = stream.listen((Operation op) { | 33 subscription = stream.listen((Operation op) { |
| 33 Future future = driver.perform(op); | 34 Future future = driver.perform(op); |
| 34 if (future != null) { | 35 if (future != null) { |
| 35 logger.log(Level.FINE, 'pausing operations for ${op.runtimeType}'); | 36 logger.log(Level.FINE, 'pausing operations for ${op.runtimeType}'); |
| 36 subscription.pause(future.then((_) { | 37 subscription.pause(future.then((_) { |
| 37 logger.log(Level.FINE, 'resuming operations'); | 38 logger.log(Level.FINE, 'resuming operations'); |
| 38 })); | 39 })); |
| 39 } | 40 } |
| 40 }, onDone: () { | 41 }, onDone: () { |
| 41 subscription.cancel(); | 42 subscription.cancel(); |
| 42 driver.stopServer(SHUTDOWN_TIMEOUT); | 43 driver.stopServer(SHUTDOWN_TIMEOUT); |
| 43 }, onError: (e, s) { | 44 }, onError: (e, s) { |
| 44 subscription.cancel(); | 45 subscription.cancel(); |
| 45 logger.log(Level.SEVERE, '$e\n$s'); | 46 logger.log(Level.SEVERE, '$e\n$s'); |
| 46 driver.stopServer(SHUTDOWN_TIMEOUT); | 47 driver.stopServer(SHUTDOWN_TIMEOUT); |
| 47 }); | 48 }); |
| 48 driver.runComplete.then((Results results) { | 49 driver.runComplete.then((Results results) { |
| 49 results.printResults(); | 50 results.printResults(); |
| 50 }).whenComplete(() { | 51 }).whenComplete(() { |
| 51 return subscription.cancel(); | 52 return subscription.cancel(); |
| 52 }); | 53 }); |
| 53 } | 54 } |
| 54 | 55 |
| 55 const DIAGNOSTIC_PORT_OPTION = 'diagnosticPort'; | 56 const DIAGNOSTIC_PORT_OPTION = 'diagnosticPort'; |
| 56 const HELP_CMDLINE_OPTION = 'help'; | 57 const HELP_CMDLINE_OPTION = 'help'; |
| 57 const INPUT_CMDLINE_OPTION = 'input'; | 58 const INPUT_CMDLINE_OPTION = 'input'; |
| 58 const MAP_OPTION = 'map'; | 59 const MAP_OPTION = 'map'; |
| 60 const NEW_TASK_MODEL_OPTION = 'newTaskModel'; |
| 59 | 61 |
| 60 /** | 62 /** |
| 61 * The amount of time to give the server to respond to a shutdown request | 63 * The amount of time to give the server to respond to a shutdown request |
| 62 * before forcibly terminating it. | 64 * before forcibly terminating it. |
| 63 */ | 65 */ |
| 64 const Duration SHUTDOWN_TIMEOUT = const Duration(seconds: 25); | 66 const Duration SHUTDOWN_TIMEOUT = const Duration(seconds: 25); |
| 65 | 67 |
| 66 const TMP_SRC_DIR_OPTION = 'tmpSrcDir'; | 68 const TMP_SRC_DIR_OPTION = 'tmpSrcDir'; |
| 67 const VERBOSE_CMDLINE_OPTION = 'verbose'; | 69 const VERBOSE_CMDLINE_OPTION = 'verbose'; |
| 68 const VERY_VERBOSE_CMDLINE_OPTION = 'vv'; | 70 const VERY_VERBOSE_CMDLINE_OPTION = 'vv'; |
| 69 | 71 |
| 70 /** | 72 /** |
| 71 * Open and return the input stream specifying how this client | 73 * Open and return the input stream specifying how this client |
| 72 * should interact with the analysis server. | 74 * should interact with the analysis server. |
| 73 */ | 75 */ |
| 74 Stream<Operation> openInput(PerfArgs args) { | 76 Stream<Operation> openInput(PerfArgs args) { |
| 75 var logger = new Logger('openInput'); | 77 var logger = new Logger('openInput'); |
| 76 Stream<List<int>> inputRaw; | 78 Stream<List<int>> inputRaw; |
| 77 if (args.inputPath == 'stdin') { | 79 if (args.inputPath == 'stdin') { |
| 78 inputRaw = stdin; | 80 inputRaw = stdin; |
| 79 } else { | 81 } else { |
| 80 inputRaw = new File(args.inputPath).openRead(); | 82 inputRaw = new File(args.inputPath).openRead(); |
| 81 } | 83 } |
| 82 args.srcPathMap.forEach((oldPath, newPath) { | 84 for (PathMapEntry entry in args.srcPathMap.entries) { |
| 83 logger.log( | 85 logger.log(Level.INFO, 'mapping source path\n' |
| 84 Level.INFO, 'mapping source path\n from $oldPath\n to $newPath'); | 86 ' from ${entry.oldSrcPrefix}\n to ${entry.newSrcPrefix}'); |
| 85 }); | 87 } |
| 86 logger.log(Level.INFO, 'tmpSrcDir: ${args.tmpSrcDirPath}'); | 88 logger.log(Level.INFO, 'tmpSrcDir: ${args.tmpSrcDirPath}'); |
| 87 return inputRaw | 89 return inputRaw |
| 88 .transform(SYSTEM_ENCODING.decoder) | 90 .transform(SYSTEM_ENCODING.decoder) |
| 89 .transform(new LineSplitter()) | 91 .transform(new LineSplitter()) |
| 90 .transform(new InputConverter(args.tmpSrcDirPath, args.srcPathMap, | 92 .transform(new InputConverter(args.tmpSrcDirPath, args.srcPathMap)); |
| 91 diagnosticPort: args.diagnosticPort)); | |
| 92 } | 93 } |
| 93 | 94 |
| 94 /** | 95 /** |
| 95 * Parse the command line arguments. | 96 * Parse the command line arguments. |
| 96 */ | 97 */ |
| 97 PerfArgs parseArgs(List<String> rawArgs) { | 98 PerfArgs parseArgs(List<String> rawArgs) { |
| 98 ArgParser parser = new ArgParser(); | 99 ArgParser parser = new ArgParser(); |
| 99 | 100 |
| 100 parser.addOption(INPUT_CMDLINE_OPTION, abbr: 'i', help: '<filePath>\n' | 101 parser.addOption(INPUT_CMDLINE_OPTION, abbr: 'i', help: '<filePath>\n' |
| 101 'The input file specifying how this client should interact with the server
.\n' | 102 'The input file specifying how this client should interact with the server
.\n' |
| 102 'If the input file name is "stdin", then the instructions are read from st
andard input.'); | 103 'If the input file name is "stdin", then the instructions are read from st
andard input.'); |
| 103 parser.addOption(MAP_OPTION, | 104 parser.addOption(MAP_OPTION, |
| 104 abbr: 'm', | 105 abbr: 'm', |
| 105 allowMultiple: true, | 106 allowMultiple: true, |
| 106 splitCommas: false, | 107 splitCommas: false, |
| 107 help: '<oldSrcPath>,<newSrcPath>\n' | 108 help: '<oldSrcPath>,<newSrcPath>\n' |
| 108 'This option defines a mapping from the original source directory <oldSrcP
ath>\n' | 109 'This option defines a mapping from the original source directory <oldSrcP
ath>\n' |
| 109 'when the instrumentation or log file was generated\n' | 110 'when the instrumentation or log file was generated\n' |
| 110 'to the target source directory <newSrcPath> used during performance testi
ng.\n' | 111 'to the target source directory <newSrcPath> used during performance testi
ng.\n' |
| 111 'Multiple mappings can be specified.\n' | 112 'Multiple mappings can be specified.\n' |
| 112 'WARNING: The contents of the target directory will be modified'); | 113 'WARNING: The contents of the target directory will be modified'); |
| 113 parser.addOption(TMP_SRC_DIR_OPTION, abbr: 't', help: '<dirPath>\n' | 114 parser.addOption(TMP_SRC_DIR_OPTION, abbr: 't', help: '<dirPath>\n' |
| 114 'The temporary directory containing source used during performance measure
ment.\n' | 115 'The temporary directory containing source used during performance measure
ment.\n' |
| 115 'WARNING: The contents of the target directory will be modified'); | 116 'WARNING: The contents of the target directory will be modified'); |
| 117 parser.addFlag(NEW_TASK_MODEL_OPTION, |
| 118 help: "enable the use of the new task model", |
| 119 defaultsTo: false, |
| 120 negatable: false); |
| 116 parser.addOption(DIAGNOSTIC_PORT_OPTION, | 121 parser.addOption(DIAGNOSTIC_PORT_OPTION, |
| 117 abbr: 'd', | 122 abbr: 'd', |
| 118 help: 'localhost port on which server will provide diagnostic web pages'); | 123 help: 'localhost port on which server will provide diagnostic web pages'); |
| 119 parser.addFlag(VERBOSE_CMDLINE_OPTION, | 124 parser.addFlag(VERBOSE_CMDLINE_OPTION, |
| 120 abbr: 'v', help: 'Verbose logging', negatable: false); | 125 abbr: 'v', help: 'Verbose logging', negatable: false); |
| 121 parser.addFlag(VERY_VERBOSE_CMDLINE_OPTION, | 126 parser.addFlag(VERY_VERBOSE_CMDLINE_OPTION, |
| 122 help: 'Extra verbose logging', negatable: false); | 127 help: 'Extra verbose logging', negatable: false); |
| 123 parser.addFlag(HELP_CMDLINE_OPTION, | 128 parser.addFlag(HELP_CMDLINE_OPTION, |
| 124 abbr: 'h', help: 'Print this help information', negatable: false); | 129 abbr: 'h', help: 'Print this help information', negatable: false); |
| 125 | 130 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 136 bool showHelp = args[HELP_CMDLINE_OPTION] || args.rest.isNotEmpty; | 141 bool showHelp = args[HELP_CMDLINE_OPTION] || args.rest.isNotEmpty; |
| 137 | 142 |
| 138 bool isMissing(key) => args[key] == null || args[key].isEmpty; | 143 bool isMissing(key) => args[key] == null || args[key].isEmpty; |
| 139 | 144 |
| 140 perfArgs.inputPath = args[INPUT_CMDLINE_OPTION]; | 145 perfArgs.inputPath = args[INPUT_CMDLINE_OPTION]; |
| 141 if (isMissing(INPUT_CMDLINE_OPTION)) { | 146 if (isMissing(INPUT_CMDLINE_OPTION)) { |
| 142 print('missing $INPUT_CMDLINE_OPTION argument'); | 147 print('missing $INPUT_CMDLINE_OPTION argument'); |
| 143 showHelp = true; | 148 showHelp = true; |
| 144 } | 149 } |
| 145 | 150 |
| 146 perfArgs.srcPathMap = <String, String>{}; | |
| 147 for (String pair in args[MAP_OPTION]) { | 151 for (String pair in args[MAP_OPTION]) { |
| 148 if (pair is String) { | 152 if (pair is String) { |
| 149 int index = pair.indexOf(','); | 153 int index = pair.indexOf(','); |
| 150 if (index != -1 && pair.indexOf(',', index + 1) == -1) { | 154 if (index != -1 && pair.indexOf(',', index + 1) == -1) { |
| 151 String oldSrcPath = _withTrailingSeparator(pair.substring(0, index)); | 155 String oldSrcPrefix = _withTrailingSeparator(pair.substring(0, index)); |
| 152 String newSrcPath = _withTrailingSeparator(pair.substring(index + 1)); | 156 String newSrcPrefix = _withTrailingSeparator(pair.substring(index + 1)); |
| 153 if (new Directory(newSrcPath).existsSync()) { | 157 if (new Directory(newSrcPrefix).existsSync()) { |
| 154 perfArgs.srcPathMap[oldSrcPath] = newSrcPath; | 158 perfArgs.srcPathMap.add(oldSrcPrefix, newSrcPrefix); |
| 155 continue; | 159 continue; |
| 156 } | 160 } |
| 157 } | 161 } |
| 158 } | 162 } |
| 159 print('must specifiy $MAP_OPTION <oldSrcPath>,<newSrcPath>'); | 163 print('must specifiy $MAP_OPTION <oldSrcPath>,<newSrcPath>'); |
| 160 showHelp = true; | 164 showHelp = true; |
| 161 } | 165 } |
| 162 | 166 |
| 163 perfArgs.tmpSrcDirPath = _withTrailingSeparator(args[TMP_SRC_DIR_OPTION]); | 167 perfArgs.tmpSrcDirPath = _withTrailingSeparator(args[TMP_SRC_DIR_OPTION]); |
| 164 if (isMissing(TMP_SRC_DIR_OPTION)) { | 168 if (isMissing(TMP_SRC_DIR_OPTION)) { |
| 165 print('missing $TMP_SRC_DIR_OPTION argument'); | 169 print('missing $TMP_SRC_DIR_OPTION argument'); |
| 166 showHelp = true; | 170 showHelp = true; |
| 167 } | 171 } |
| 168 | 172 |
| 173 perfArgs.newTaskModel = args[NEW_TASK_MODEL_OPTION]; |
| 174 |
| 169 String portText = args[DIAGNOSTIC_PORT_OPTION]; | 175 String portText = args[DIAGNOSTIC_PORT_OPTION]; |
| 170 if (portText != null) { | 176 if (portText != null) { |
| 171 perfArgs.diagnosticPort = int.parse(portText, onError: (s) { | 177 perfArgs.diagnosticPort = int.parse(portText, onError: (s) { |
| 172 print('invalid $DIAGNOSTIC_PORT_OPTION: $s'); | 178 print('invalid $DIAGNOSTIC_PORT_OPTION: $s'); |
| 173 showHelp = true; | 179 showHelp = true; |
| 174 }); | 180 }); |
| 175 } | 181 } |
| 176 | 182 |
| 177 if (args[VERY_VERBOSE_CMDLINE_OPTION] || rawArgs.contains('-vv')) { | 183 if (args[VERY_VERBOSE_CMDLINE_OPTION] || rawArgs.contains('-vv')) { |
| 178 Logger.root.level = Level.FINE; | 184 Logger.root.level = Level.FINE; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 219 * used to drive performance measurement, | 225 * used to drive performance measurement, |
| 220 * or 'stdin' if this information should be read from standard input. | 226 * or 'stdin' if this information should be read from standard input. |
| 221 */ | 227 */ |
| 222 String inputPath; | 228 String inputPath; |
| 223 | 229 |
| 224 /** | 230 /** |
| 225 * A mapping from the original source directory | 231 * A mapping from the original source directory |
| 226 * when the instrumentation or log file was generated | 232 * when the instrumentation or log file was generated |
| 227 * to the target source directory used during performance testing. | 233 * to the target source directory used during performance testing. |
| 228 */ | 234 */ |
| 229 Map<String, String> srcPathMap; | 235 final PathMap srcPathMap = new PathMap(); |
| 230 | 236 |
| 231 /** | 237 /** |
| 232 * The temporary directory containing source used during performance measureme
nt. | 238 * The temporary directory containing source used during performance measureme
nt. |
| 233 */ | 239 */ |
| 234 String tmpSrcDirPath; | 240 String tmpSrcDirPath; |
| 235 | 241 |
| 236 /** | 242 /** |
| 237 * The diagnostic port for Analysis Server or `null` if none. | 243 * The diagnostic port for Analysis Server or `null` if none. |
| 238 */ | 244 */ |
| 239 int diagnosticPort; | 245 int diagnosticPort; |
| 246 |
| 247 /** |
| 248 * `true` if the server should run using the new task model. |
| 249 */ |
| 250 bool newTaskModel; |
| 240 } | 251 } |
| OLD | NEW |