OLD | NEW |
---|---|
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 import 'dart:async'; | 5 import 'dart:async'; |
6 import 'dart:collection'; | 6 import 'dart:collection'; |
7 import 'dart:typed_data'; | 7 import 'dart:typed_data'; |
8 | 8 |
9 import 'package:analyzer/dart/ast/ast.dart'; | 9 import 'package:analyzer/dart/ast/ast.dart'; |
10 import 'package:analyzer/dart/element/element.dart' show CompilationUnitElement; | 10 import 'package:analyzer/dart/element/element.dart' show CompilationUnitElement; |
(...skipping 900 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
911 referencingName, | 911 referencingName, |
912 getIndex, | 912 getIndex, |
913 interactive | 913 interactive |
914 } | 914 } |
915 | 915 |
916 /** | 916 /** |
917 * Instances of this class schedule work in multiple [AnalysisDriver]s so that | 917 * Instances of this class schedule work in multiple [AnalysisDriver]s so that |
918 * work with the highest priority is performed first. | 918 * work with the highest priority is performed first. |
919 */ | 919 */ |
920 class AnalysisDriverScheduler { | 920 class AnalysisDriverScheduler { |
921 /** | |
922 * Time interval in milliseconds before pumping the event queue. | |
923 * | |
924 * Relinquishing execution flow and running event loop after every task has | |
Brian Wilkerson
2016/12/01 17:12:27
"running event" --> "running the event"
| |
925 * too much overhead. Instead we use a fixed length of time, so we can spend | |
926 * less time overall and still respond quick enough. | |
927 */ | |
928 static const int _MS_BEFORE_PUMPING_EVENT_QUEUE = 2; | |
929 | |
930 /** | |
931 * Event queue pumping is required to allow IO and other asynchronous data | |
932 * processing while analysis is active. For example Analysis Server needs to | |
933 * be able to process `updateContent` or `setPriorityFiles` requests while | |
934 * background analysis is in progress. | |
935 * | |
936 * The number of pumpings is arbitrary, might be changed if we see that | |
937 * analysis or other data processing tasks are starving. Ideally we would | |
938 * need to run all asynchronous operations using a single global scheduler. | |
939 */ | |
940 static const int _NUMBER_OF_EVENT_QUEUE_PUMPINGS = 128; | |
941 | |
921 final PerformanceLog _logger; | 942 final PerformanceLog _logger; |
922 final List<AnalysisDriver> _drivers = []; | 943 final List<AnalysisDriver> _drivers = []; |
923 final Monitor _hasWork = new Monitor(); | 944 final Monitor _hasWork = new Monitor(); |
924 final StatusSupport _statusSupport = new StatusSupport(); | 945 final StatusSupport _statusSupport = new StatusSupport(); |
925 | 946 |
926 bool _started = false; | 947 bool _started = false; |
927 | 948 |
928 AnalysisDriverScheduler(this._logger); | 949 AnalysisDriverScheduler(this._logger); |
929 | 950 |
930 /** | 951 /** |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
970 _drivers.remove(driver); | 991 _drivers.remove(driver); |
971 _statusSupport.transitionToAnalyzing(); | 992 _statusSupport.transitionToAnalyzing(); |
972 _hasWork.notify(); | 993 _hasWork.notify(); |
973 } | 994 } |
974 | 995 |
975 /** | 996 /** |
976 * Run infinitely analysis cycle, selecting the drivers with the highest | 997 * Run infinitely analysis cycle, selecting the drivers with the highest |
977 * priority first. | 998 * priority first. |
978 */ | 999 */ |
979 Future<Null> _run() async { | 1000 Future<Null> _run() async { |
1001 Stopwatch timer = new Stopwatch()..start(); | |
980 PerformanceLogSection analysisSection; | 1002 PerformanceLogSection analysisSection; |
981 while (true) { | 1003 while (true) { |
982 // Pump the event queue to allow IO and other asynchronous data | 1004 // Pump the event queue. |
983 // processing while analysis is active. For example Analysis Server | 1005 if (timer.elapsedMilliseconds > _MS_BEFORE_PUMPING_EVENT_QUEUE) { |
984 // needs to be able to process `updateContent` or `setPriorityFiles` | 1006 await _pumpEventQueue(_NUMBER_OF_EVENT_QUEUE_PUMPINGS); |
985 // requests while background analysis is in progress. | 1007 timer.reset(); |
986 // | 1008 } |
987 // The number of pumpings is arbitrary, might be changed if we see that | |
988 // analysis or other data processing tasks are starving. Ideally we | |
989 // would need to be able to set priority of (continuous) asynchronous | |
990 // tasks. | |
991 await _pumpEventQueue(128); | |
992 | 1009 |
993 await _hasWork.signal; | 1010 await _hasWork.signal; |
994 | 1011 |
995 if (analysisSection == null) { | 1012 if (analysisSection == null) { |
996 analysisSection = _logger.enter('Analyzing'); | 1013 analysisSection = _logger.enter('Analyzing'); |
997 } | 1014 } |
998 | 1015 |
999 // Find the driver with the highest priority. | 1016 // Find the driver with the highest priority. |
1000 AnalysisDriver bestDriver; | 1017 AnalysisDriver bestDriver; |
1001 AnalysisDriverPriority bestPriority = AnalysisDriverPriority.nothing; | 1018 AnalysisDriverPriority bestPriority = AnalysisDriverPriority.nothing; |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1259 final String name; | 1276 final String name; |
1260 final Completer<List<String>> completer = new Completer<List<String>>(); | 1277 final Completer<List<String>> completer = new Completer<List<String>>(); |
1261 | 1278 |
1262 final List<String> referencingFiles = <String>[]; | 1279 final List<String> referencingFiles = <String>[]; |
1263 final Set<String> checkedFiles = new Set<String>(); | 1280 final Set<String> checkedFiles = new Set<String>(); |
1264 final List<String> filesToCheck = <String>[]; | 1281 final List<String> filesToCheck = <String>[]; |
1265 | 1282 |
1266 _FilesReferencingNameTask(this.driver, this.name); | 1283 _FilesReferencingNameTask(this.driver, this.name); |
1267 | 1284 |
1268 /** | 1285 /** |
1269 * Perform work for a fixed length of time, and either complete the | 1286 * Perform a single piece of work, and either complete the [completer] and |
1270 * [completer] and return `true` to indicate that the task is done, return | 1287 * return `true` to indicate that the task is done, return `false` to indicate |
1271 * `false` to indicate that the task should continue to be run. | 1288 * that the task should continue to be run. |
1272 * | |
1273 * Relinquishing execution flow and running event loop after every file | |
1274 * works, but has too much overhead. Instead we use a fixed length of time, | |
1275 * so we can spend less time overall and keep quick enough response time. | |
1276 */ | 1289 */ |
1277 Future<bool> perform() async { | 1290 Future<bool> perform() async { |
1278 Stopwatch timer = new Stopwatch()..start(); | 1291 // Prepare files to check. |
1279 while (timer.elapsedMilliseconds < 5) { | 1292 if (filesToCheck.isEmpty) { |
1280 // Prepare files to check. | 1293 Set<String> newFiles = driver.addedFiles.difference(checkedFiles); |
1281 if (filesToCheck.isEmpty) { | 1294 filesToCheck.addAll(newFiles); |
1282 Set<String> newFiles = driver.addedFiles.difference(checkedFiles); | 1295 } |
1283 filesToCheck.addAll(newFiles); | |
1284 } | |
1285 | 1296 |
1286 // If no more files to check, complete and done. | 1297 // If no more files to check, complete and done. |
1287 if (filesToCheck.isEmpty) { | 1298 if (filesToCheck.isEmpty) { |
1288 completer.complete(referencingFiles); | 1299 completer.complete(referencingFiles); |
1289 return true; | 1300 return true; |
1290 } | 1301 } |
1291 | 1302 |
1292 // Check the next file. | 1303 // Check the next file. |
1293 String path = filesToCheck.removeLast(); | 1304 String path = filesToCheck.removeLast(); |
1294 FileState file = driver._fsState.getFileForPath(path); | 1305 FileState file = driver._fsState.getFileForPath(path); |
1295 if (file.referencedNames.contains(name)) { | 1306 if (file.referencedNames.contains(name)) { |
1296 referencingFiles.add(path); | 1307 referencingFiles.add(path); |
1297 } | |
1298 checkedFiles.add(path); | |
1299 } | 1308 } |
1309 checkedFiles.add(path); | |
1300 | 1310 |
1301 // We're not done yet. | 1311 // We're not done yet. |
1302 return false; | 1312 return false; |
1303 } | 1313 } |
1304 } | 1314 } |
1305 | 1315 |
1306 /** | 1316 /** |
1307 * TODO(scheglov) document | 1317 * TODO(scheglov) document |
1308 */ | 1318 */ |
1309 class _LibraryContext { | 1319 class _LibraryContext { |
1310 final FileState file; | 1320 final FileState file; |
1311 final SummaryDataStore store; | 1321 final SummaryDataStore store; |
1312 _LibraryContext(this.file, this.store); | 1322 _LibraryContext(this.file, this.store); |
1313 } | 1323 } |
OLD | NEW |