| 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.analysis.timing; | 5 library server.performance.analysis.timing; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:io'; | 8 import 'dart:io'; |
| 9 | 9 |
| 10 import 'package:analysis_server/src/protocol.dart'; | 10 import 'package:analysis_server/src/protocol.dart'; |
| 11 import 'package:args/args.dart'; | 11 import 'package:args/args.dart'; |
| 12 import 'package:test_reflective_loader/test_reflective_loader.dart'; | 12 import 'package:test_reflective_loader/test_reflective_loader.dart'; |
| 13 import 'package:unittest/unittest.dart'; | 13 import 'package:unittest/unittest.dart'; |
| 14 | 14 |
| 15 import '../../test/utils.dart'; | 15 import '../../test/utils.dart'; |
| 16 import 'performance_tests.dart'; | 16 import 'performance_tests.dart'; |
| 17 | 17 |
| 18 /** | 18 /** |
| 19 * Pass in the directory of the source to be analyzed as option `--source`, | 19 * Pass in the directory of the source to be analyzed as option `--source`, |
| 20 * optionally specify a priority file with `--priority` and the specific | 20 * optionally specify a priority file with `--priority` and the specific |
| 21 * test to run with `--test`. If no test is specified, the default is | 21 * test to run with `--metric`. If no test is specified, the default is |
| 22 * `analysis`. | 22 * `analysis`. |
| 23 */ | 23 */ |
| 24 main(List<String> arguments) { | 24 main(List<String> arguments) { |
| 25 initializeTestEnvironment(); | 25 initializeTestEnvironment(); |
| 26 ArgParser parser = _createArgParser(); | 26 ArgParser parser = _createArgParser(); |
| 27 var args = parser.parse(arguments); | 27 var args = parser.parse(arguments); |
| 28 if (args[SOURCE_OPTION] == null) { | 28 if (args[SOURCE_OPTION] == null) { |
| 29 print('path to source directory must be specified'); | 29 print('path to source directory must be specified'); |
| 30 exit(1); | 30 exit(1); |
| 31 } | 31 } |
| 32 source = args[SOURCE_OPTION]; | 32 source = args[SOURCE_OPTION]; |
| 33 priorityFile = args[PRIORITY_FILE_OPTION]; | 33 priorityFile = args[PRIORITY_FILE_OPTION]; |
| 34 var metricNameParam = args[METRIC_NAME_OPTION] ?? DEFAULT_METRIC; | 34 metricNames.addAll(args[METRIC_NAME_OPTION]); |
| 35 unittestConfiguration.timeout = new Duration(minutes: 20); |
| 35 | 36 |
| 36 metricNames.addAll(metricNameParam); | 37 if (metricNames.isEmpty) { |
| 37 | 38 defineReflectiveTests(AnalysisTimingTest); |
| 38 defineReflectiveTests(TimingTest); | 39 } else { |
| 40 defineReflectiveTests(SubscriptionTimingTest); |
| 41 } |
| 39 } | 42 } |
| 40 | 43 |
| 41 const DEFAULT_METRIC = 'analysis'; | 44 const DEFAULT_METRIC = 'analysis'; |
| 42 const METRIC_NAME_OPTION = 'metric'; | 45 const METRIC_NAME_OPTION = 'metric'; |
| 43 const PRIORITY_FILE_OPTION = 'priority'; | 46 const PRIORITY_FILE_OPTION = 'priority'; |
| 44 const SOURCE_OPTION = 'source'; | 47 const SOURCE_OPTION = 'source'; |
| 45 | 48 |
| 46 final metricNames = <String>[]; | 49 final metricNames = <String>[]; |
| 47 String priorityFile; | 50 String priorityFile; |
| 48 String source; | 51 String source; |
| 49 | 52 |
| 50 ArgParser _createArgParser() => new ArgParser() | 53 ArgParser _createArgParser() => new ArgParser() |
| 51 ..addOption(METRIC_NAME_OPTION, | 54 ..addOption(METRIC_NAME_OPTION, |
| 52 help: 'metric name (defaults to `analysis`)', allowMultiple: true) | 55 help: 'metric name (defaults to `analysis`)', allowMultiple: true) |
| 53 ..addOption(SOURCE_OPTION, help: 'full path to source directory for analysis') | 56 ..addOption(SOURCE_OPTION, help: 'full path to source directory for analysis') |
| 54 ..addOption(PRIORITY_FILE_OPTION, | 57 ..addOption(PRIORITY_FILE_OPTION, |
| 55 help: '(optional) full path to a priority file'); | 58 help: '(optional) full path to a priority file'); |
| 56 | 59 |
| 57 class AbstractTimingTest extends AbstractAnalysisServerPerformanceTest { | 60 class AbstractTimingTest extends AbstractAnalysisServerPerformanceTest { |
| 58 @override | 61 @override |
| 59 Future setUp() => super.setUp().then((_) { | 62 Future setUp() => super.setUp().then((_) { |
| 60 sourceDirectory = new Directory(source); | 63 sourceDirectory = new Directory(source); |
| 61 subscribeToStatusNotifications(); | 64 subscribeToStatusNotifications(); |
| 62 }); | 65 }); |
| 63 } | 66 } |
| 64 | 67 |
| 68 @reflectiveTest |
| 69 class AnalysisTimingTest extends AbstractTimingTest { |
| 70 Future test_timing() { |
| 71 // Set root after subscribing to avoid empty notifications. |
| 72 setAnalysisRoot(); |
| 73 |
| 74 stopwatch.start(); |
| 75 return analysisFinished.then((_) { |
| 76 print('analysis completed in ${stopwatch.elapsed}'); |
| 77 stopwatch.reset(); |
| 78 }); |
| 79 } |
| 80 } |
| 81 |
| 65 class Metric { | 82 class Metric { |
| 66 List<Duration> timings = <Duration>[]; | 83 List<Duration> timings = <Duration>[]; |
| 67 Stream eventStream; | 84 Stream eventStream; |
| 68 AnalysisService service; | 85 AnalysisService service; |
| 69 String name; | 86 String name; |
| 70 Metric(this.name, this.service, this.eventStream); | 87 Metric(this.name, this.service, this.eventStream); |
| 71 String toString() => '$name: $service, ${eventStream.runtimeType}, $timings'; | 88 String toString() => '$name: $service, ${eventStream.runtimeType}, $timings'; |
| 72 } | 89 } |
| 73 | 90 |
| 74 @reflectiveTest | 91 @reflectiveTest |
| 75 class TimingTest extends AbstractTimingTest { | 92 class SubscriptionTimingTest extends AbstractTimingTest { |
| 76 List<Metric> _metrics; | 93 List<Metric> _metrics; |
| 77 | 94 |
| 78 List<Metric> get metrics => | 95 List<Metric> get metrics => |
| 79 _metrics ??= metricNames.map((name) => getMetric(name)).toList(); | 96 _metrics ??= metricNames.map((name) => getMetric(name)).toList(); |
| 80 | 97 |
| 81 Metric getMetric(String name) { | 98 Metric getMetric(String name) { |
| 82 switch (name) { | 99 switch (name) { |
| 83 case 'folding': | 100 case 'folding': |
| 84 return new Metric(name, AnalysisService.FOLDING, onAnalysisFolding); | 101 return new Metric(name, AnalysisService.FOLDING, onAnalysisFolding); |
| 85 case 'highlighting': | 102 case 'highlighting': |
| (...skipping 12 matching lines...) Expand all Loading... |
| 98 name, AnalysisService.OCCURRENCES, onAnalysisOccurrences); | 115 name, AnalysisService.OCCURRENCES, onAnalysisOccurrences); |
| 99 case 'overrides': | 116 case 'overrides': |
| 100 return new Metric(name, AnalysisService.OVERRIDES, onAnalysisOverrides); | 117 return new Metric(name, AnalysisService.OVERRIDES, onAnalysisOverrides); |
| 101 } | 118 } |
| 102 print('no metric found for $name'); | 119 print('no metric found for $name'); |
| 103 exit(1); | 120 exit(1); |
| 104 return null; // Won't get here. | 121 return null; // Won't get here. |
| 105 } | 122 } |
| 106 | 123 |
| 107 Future test_timing() { | 124 Future test_timing() { |
| 108 //debugStdio(); | 125 // debugStdio(); |
| 109 | 126 |
| 110 expect(metrics, isNotEmpty); | 127 expect(metrics, isNotEmpty); |
| 111 expect(priorityFile, isNotNull, | 128 expect(priorityFile, isNotNull, |
| 112 reason: 'A priority file must be specified for ' | 129 reason: 'A priority file must be specified for ' |
| 113 '${metrics.first.name} testing.'); | 130 '${metrics.first.name} testing.'); |
| 114 | 131 |
| 115 stopwatch.start(); | 132 stopwatch.start(); |
| 116 | 133 |
| 117 metrics.forEach((Metric m) => m.eventStream.listen((_) { | 134 metrics.forEach((Metric m) => m.eventStream.listen((_) { |
| 118 m.timings.add( | 135 m.timings.add( |
| (...skipping 10 matching lines...) Expand all Loading... |
| 129 | 146 |
| 130 sendAnalysisSetPriorityFiles([priorityFile]); | 147 sendAnalysisSetPriorityFiles([priorityFile]); |
| 131 | 148 |
| 132 return analysisFinished.then((_) { | 149 return analysisFinished.then((_) { |
| 133 print('analysis completed in ${stopwatch.elapsed}'); | 150 print('analysis completed in ${stopwatch.elapsed}'); |
| 134 metrics.forEach((Metric m) => print('${m.name} timings: ${m.timings}')); | 151 metrics.forEach((Metric m) => print('${m.name} timings: ${m.timings}')); |
| 135 stopwatch.reset(); | 152 stopwatch.reset(); |
| 136 }); | 153 }); |
| 137 } | 154 } |
| 138 } | 155 } |
| OLD | NEW |