Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(160)

Side by Side Diff: pkg/analyzer/lib/src/dart/analysis/driver.dart

Issue 2540403002: Move running tasks for fixed time to the scheduler. (Closed)
Patch Set: Extract constants and move comments. Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698