| 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 | 14 |
| 14 import 'driver.dart'; | 15 import 'driver.dart'; |
| 15 import 'input_converter.dart'; | 16 import 'input_converter.dart'; |
| 16 import 'operation.dart'; | 17 import 'operation.dart'; |
| 17 | 18 |
| 18 /** | 19 /** |
| 19 * The amount of time to give the server to respond to a shutdown request | |
| 20 * before forcibly terminating it. | |
| 21 */ | |
| 22 const Duration SHUTDOWN_TIMEOUT = const Duration(seconds: 25); | |
| 23 | |
| 24 /** | |
| 25 * Launch and interact with the analysis server. | 20 * Launch and interact with the analysis server. |
| 26 */ | 21 */ |
| 27 main(List<String> rawArgs) { | 22 main(List<String> rawArgs) { |
| 28 Logger logger = new Logger('Performance Measurement Client'); | 23 Logger logger = new Logger('Performance Measurement Client'); |
| 29 logger.onRecord.listen((LogRecord rec) { | 24 logger.onRecord.listen((LogRecord rec) { |
| 30 print(rec.message); | 25 print(rec.message); |
| 31 }); | 26 }); |
| 32 PerfArgs args = parseArgs(rawArgs); | 27 PerfArgs args = parseArgs(rawArgs); |
| 33 | 28 |
| 34 Driver driver = new Driver(logger); | 29 Driver driver = new Driver(logger); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 50 logger.log(Level.SEVERE, '$e\n$s'); | 45 logger.log(Level.SEVERE, '$e\n$s'); |
| 51 driver.stopServer(SHUTDOWN_TIMEOUT); | 46 driver.stopServer(SHUTDOWN_TIMEOUT); |
| 52 }); | 47 }); |
| 53 driver.runComplete.then((Results results) { | 48 driver.runComplete.then((Results results) { |
| 54 results.printResults(); | 49 results.printResults(); |
| 55 }).whenComplete(() { | 50 }).whenComplete(() { |
| 56 return subscription.cancel(); | 51 return subscription.cancel(); |
| 57 }); | 52 }); |
| 58 } | 53 } |
| 59 | 54 |
| 55 const DIAGNOSTIC_PORT_OPTION = 'diagnosticPort'; |
| 60 const HELP_CMDLINE_OPTION = 'help'; | 56 const HELP_CMDLINE_OPTION = 'help'; |
| 61 const INPUT_CMDLINE_OPTION = 'input'; | 57 const INPUT_CMDLINE_OPTION = 'input'; |
| 62 const MAP_OPTION = 'map'; | 58 const MAP_OPTION = 'map'; |
| 59 |
| 60 /** |
| 61 * The amount of time to give the server to respond to a shutdown request |
| 62 * before forcibly terminating it. |
| 63 */ |
| 64 const Duration SHUTDOWN_TIMEOUT = const Duration(seconds: 25); |
| 65 |
| 63 const TMP_SRC_DIR_OPTION = 'tmpSrcDir'; | 66 const TMP_SRC_DIR_OPTION = 'tmpSrcDir'; |
| 64 const VERBOSE_CMDLINE_OPTION = 'verbose'; | 67 const VERBOSE_CMDLINE_OPTION = 'verbose'; |
| 65 const VERY_VERBOSE_CMDLINE_OPTION = 'vv'; | 68 const VERY_VERBOSE_CMDLINE_OPTION = 'vv'; |
| 66 | 69 |
| 67 /** | 70 /** |
| 68 * Open and return the input stream specifying how this client | 71 * Open and return the input stream specifying how this client |
| 69 * should interact with the analysis server. | 72 * should interact with the analysis server. |
| 70 */ | 73 */ |
| 71 Stream<Operation> openInput(PerfArgs args) { | 74 Stream<Operation> openInput(PerfArgs args) { |
| 72 var logger = new Logger('openInput'); | 75 var logger = new Logger('openInput'); |
| 73 Stream<List<int>> inputRaw; | 76 Stream<List<int>> inputRaw; |
| 74 if (args.inputPath == 'stdin') { | 77 if (args.inputPath == 'stdin') { |
| 75 inputRaw = stdin; | 78 inputRaw = stdin; |
| 76 } else { | 79 } else { |
| 77 inputRaw = new File(args.inputPath).openRead(); | 80 inputRaw = new File(args.inputPath).openRead(); |
| 78 } | 81 } |
| 79 args.srcPathMap.forEach((oldPath, newPath) { | 82 args.srcPathMap.forEach((oldPath, newPath) { |
| 80 logger.log( | 83 logger.log( |
| 81 Level.INFO, 'mapping source path\n from $oldPath\n to $newPath'); | 84 Level.INFO, 'mapping source path\n from $oldPath\n to $newPath'); |
| 82 }); | 85 }); |
| 83 logger.log(Level.INFO, 'tmpSrcDir: ${args.tmpSrcDirPath}'); | 86 logger.log(Level.INFO, 'tmpSrcDir: ${args.tmpSrcDirPath}'); |
| 84 return inputRaw | 87 return inputRaw |
| 85 .transform(SYSTEM_ENCODING.decoder) | 88 .transform(SYSTEM_ENCODING.decoder) |
| 86 .transform(new LineSplitter()) | 89 .transform(new LineSplitter()) |
| 87 .transform(new InputConverter(args.tmpSrcDirPath, args.srcPathMap)); | 90 .transform(new InputConverter(args.tmpSrcDirPath, args.srcPathMap, |
| 91 diagnosticPort: args.diagnosticPort)); |
| 88 } | 92 } |
| 89 | 93 |
| 90 /** | 94 /** |
| 91 * Parse the command line arguments. | 95 * Parse the command line arguments. |
| 92 */ | 96 */ |
| 93 PerfArgs parseArgs(List<String> rawArgs) { | 97 PerfArgs parseArgs(List<String> rawArgs) { |
| 94 ArgParser parser = new ArgParser(); | 98 ArgParser parser = new ArgParser(); |
| 95 | 99 |
| 96 parser.addOption(INPUT_CMDLINE_OPTION, abbr: 'i', help: '<filePath>\n' | 100 parser.addOption(INPUT_CMDLINE_OPTION, abbr: 'i', help: '<filePath>\n' |
| 97 'The input file specifying how this client should interact with the server
.\n' | 101 'The input file specifying how this client should interact with the server
.\n' |
| 98 'If the input file name is "stdin", then the instructions are read from st
andard input.'); | 102 'If the input file name is "stdin", then the instructions are read from st
andard input.'); |
| 99 parser.addOption(MAP_OPTION, | 103 parser.addOption(MAP_OPTION, |
| 100 abbr: 'm', | 104 abbr: 'm', |
| 101 allowMultiple: true, | 105 allowMultiple: true, |
| 102 splitCommas: false, | 106 splitCommas: false, |
| 103 help: '<oldSrcPath>,<newSrcPath>\n' | 107 help: '<oldSrcPath>,<newSrcPath>\n' |
| 104 'This option defines a mapping from the original source directory <oldSrcP
ath>\n' | 108 'This option defines a mapping from the original source directory <oldSrcP
ath>\n' |
| 105 'when the instrumentation or log file was generated\n' | 109 'when the instrumentation or log file was generated\n' |
| 106 'to the target source directory <newSrcPath> used during performance testi
ng.\n' | 110 'to the target source directory <newSrcPath> used during performance testi
ng.\n' |
| 107 'Multiple mappings can be specified.\n' | 111 'Multiple mappings can be specified.\n' |
| 108 'WARNING: The contents of the target directory will be modified'); | 112 'WARNING: The contents of the target directory will be modified'); |
| 109 parser.addOption(TMP_SRC_DIR_OPTION, abbr: 't', help: '<dirPath>\n' | 113 parser.addOption(TMP_SRC_DIR_OPTION, abbr: 't', help: '<dirPath>\n' |
| 110 'The temporary directory containing source used during performance measure
ment.\n' | 114 'The temporary directory containing source used during performance measure
ment.\n' |
| 111 'WARNING: The contents of the target directory will be modified'); | 115 'WARNING: The contents of the target directory will be modified'); |
| 116 parser.addOption(DIAGNOSTIC_PORT_OPTION, |
| 117 abbr: 'd', |
| 118 help: 'localhost port on which server will provide diagnostic web pages'); |
| 112 parser.addFlag(VERBOSE_CMDLINE_OPTION, | 119 parser.addFlag(VERBOSE_CMDLINE_OPTION, |
| 113 abbr: 'v', help: 'Verbose logging', negatable: false); | 120 abbr: 'v', help: 'Verbose logging', negatable: false); |
| 114 parser.addFlag(VERY_VERBOSE_CMDLINE_OPTION, | 121 parser.addFlag(VERY_VERBOSE_CMDLINE_OPTION, |
| 115 help: 'Extra verbose logging', negatable: false); | 122 help: 'Extra verbose logging', negatable: false); |
| 116 parser.addFlag(HELP_CMDLINE_OPTION, | 123 parser.addFlag(HELP_CMDLINE_OPTION, |
| 117 abbr: 'h', help: 'Print this help information', negatable: false); | 124 abbr: 'h', help: 'Print this help information', negatable: false); |
| 118 | 125 |
| 119 ArgResults args; | 126 ArgResults args; |
| 120 PerfArgs perfArgs = new PerfArgs(); | 127 PerfArgs perfArgs = new PerfArgs(); |
| 121 try { | 128 try { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 134 if (isMissing(INPUT_CMDLINE_OPTION)) { | 141 if (isMissing(INPUT_CMDLINE_OPTION)) { |
| 135 print('missing $INPUT_CMDLINE_OPTION argument'); | 142 print('missing $INPUT_CMDLINE_OPTION argument'); |
| 136 showHelp = true; | 143 showHelp = true; |
| 137 } | 144 } |
| 138 | 145 |
| 139 perfArgs.srcPathMap = <String, String>{}; | 146 perfArgs.srcPathMap = <String, String>{}; |
| 140 for (String pair in args[MAP_OPTION]) { | 147 for (String pair in args[MAP_OPTION]) { |
| 141 if (pair is String) { | 148 if (pair is String) { |
| 142 int index = pair.indexOf(','); | 149 int index = pair.indexOf(','); |
| 143 if (index != -1 && pair.indexOf(',', index + 1) == -1) { | 150 if (index != -1 && pair.indexOf(',', index + 1) == -1) { |
| 144 String oldSrcPath = pair.substring(0, index); | 151 String oldSrcPath = _withTrailingSeparator(pair.substring(0, index)); |
| 145 String newSrcPath = pair.substring(index + 1); | 152 String newSrcPath = _withTrailingSeparator(pair.substring(index + 1)); |
| 146 if (new Directory(oldSrcPath).existsSync() && | 153 if (new Directory(newSrcPath).existsSync()) { |
| 147 new Directory(newSrcPath).existsSync()) { | |
| 148 perfArgs.srcPathMap[oldSrcPath] = newSrcPath; | 154 perfArgs.srcPathMap[oldSrcPath] = newSrcPath; |
| 149 continue; | 155 continue; |
| 150 } | 156 } |
| 151 } | 157 } |
| 152 } | 158 } |
| 153 print('must specifiy $MAP_OPTION <oldSrcPath>,<newSrcPath>'); | 159 print('must specifiy $MAP_OPTION <oldSrcPath>,<newSrcPath>'); |
| 154 showHelp = true; | 160 showHelp = true; |
| 155 } | 161 } |
| 156 | 162 |
| 157 perfArgs.tmpSrcDirPath = args[TMP_SRC_DIR_OPTION]; | 163 perfArgs.tmpSrcDirPath = _withTrailingSeparator(args[TMP_SRC_DIR_OPTION]); |
| 158 if (isMissing(TMP_SRC_DIR_OPTION)) { | 164 if (isMissing(TMP_SRC_DIR_OPTION)) { |
| 159 print('missing $TMP_SRC_DIR_OPTION argument'); | 165 print('missing $TMP_SRC_DIR_OPTION argument'); |
| 160 showHelp = true; | 166 showHelp = true; |
| 161 } | 167 } |
| 162 | 168 |
| 169 String portText = args[DIAGNOSTIC_PORT_OPTION]; |
| 170 if (portText != null) { |
| 171 perfArgs.diagnosticPort = int.parse(portText, onError: (s) { |
| 172 print('invalid $DIAGNOSTIC_PORT_OPTION: $s'); |
| 173 showHelp = true; |
| 174 }); |
| 175 } |
| 176 |
| 163 if (args[VERY_VERBOSE_CMDLINE_OPTION] || rawArgs.contains('-vv')) { | 177 if (args[VERY_VERBOSE_CMDLINE_OPTION] || rawArgs.contains('-vv')) { |
| 164 Logger.root.level = Level.FINE; | 178 Logger.root.level = Level.FINE; |
| 165 } else if (args[VERBOSE_CMDLINE_OPTION]) { | 179 } else if (args[VERBOSE_CMDLINE_OPTION]) { |
| 166 Logger.root.level = Level.INFO; | 180 Logger.root.level = Level.INFO; |
| 167 } else { | 181 } else { |
| 168 Logger.root.level = Level.WARNING; | 182 Logger.root.level = Level.WARNING; |
| 169 } | 183 } |
| 170 | 184 |
| 171 if (showHelp) { | 185 if (showHelp) { |
| 172 printHelp(parser); | 186 printHelp(parser); |
| 173 exit(1); | 187 exit(1); |
| 174 } | 188 } |
| 175 | 189 |
| 176 return perfArgs; | 190 return perfArgs; |
| 177 } | 191 } |
| 178 | 192 |
| 179 void printHelp(ArgParser parser) { | 193 void printHelp(ArgParser parser) { |
| 180 print(''); | 194 print(''); |
| 181 print('Launch and interact with the AnalysisServer'); | 195 print('Launch and interact with the AnalysisServer'); |
| 182 print(''); | 196 print(''); |
| 183 print(parser.usage); | 197 print(parser.usage); |
| 184 } | 198 } |
| 185 | 199 |
| 186 /** | 200 /** |
| 201 * Ensure that the given path has a trailing separator |
| 202 */ |
| 203 String _withTrailingSeparator(String dirPath) { |
| 204 if (dirPath != null && dirPath.length > 4) { |
| 205 if (!dirPath.endsWith(path.separator)) { |
| 206 return '$dirPath${path.separator}'; |
| 207 } |
| 208 } |
| 209 return dirPath; |
| 210 } |
| 211 |
| 212 /** |
| 187 * The performance measurement arguments specified on the command line. | 213 * The performance measurement arguments specified on the command line. |
| 188 */ | 214 */ |
| 189 class PerfArgs { | 215 class PerfArgs { |
| 190 | 216 |
| 191 /** | 217 /** |
| 192 * The file path of the instrumentation or log file | 218 * The file path of the instrumentation or log file |
| 193 * used to drive performance measurement, | 219 * used to drive performance measurement, |
| 194 * or 'stdin' if this information should be read from standard input. | 220 * or 'stdin' if this information should be read from standard input. |
| 195 */ | 221 */ |
| 196 String inputPath; | 222 String inputPath; |
| 197 | 223 |
| 198 /** | 224 /** |
| 199 * A mapping from the original source directory | 225 * A mapping from the original source directory |
| 200 * when the instrumentation or log file was generated | 226 * when the instrumentation or log file was generated |
| 201 * to the target source directory used during performance testing. | 227 * to the target source directory used during performance testing. |
| 202 */ | 228 */ |
| 203 Map<String, String> srcPathMap; | 229 Map<String, String> srcPathMap; |
| 204 | 230 |
| 205 /** | 231 /** |
| 206 * The temporary directory containing source used during performance measureme
nt. | 232 * The temporary directory containing source used during performance measureme
nt. |
| 207 */ | 233 */ |
| 208 String tmpSrcDirPath; | 234 String tmpSrcDirPath; |
| 235 |
| 236 /** |
| 237 * The diagnostic port for Analysis Server or `null` if none. |
| 238 */ |
| 239 int diagnosticPort; |
| 209 } | 240 } |
| OLD | NEW |