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

Side by Side Diff: pkg/analysis_server/lib/src/source/optimizing_pub_package_map_provider.dart

Issue 1089453002: Avoid redundant calls to "pub list" when multiple dependencies change. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Add missing source file. Created 5 years, 8 months 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 | Annotate | Revision Log
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 library source.optimizing_pub_package_map_provider;
6
7 import 'package:analyzer/file_system/file_system.dart';
8 import 'package:analyzer/source/package_map_provider.dart';
9 import 'package:analyzer/source/pub_package_map_provider.dart';
10 import 'package:analyzer/src/generated/sdk_io.dart';
11
12 /**
13 * Extension of [PackageMapInfo] that tracks the modification timestamps of
14 * pub dependencies. This allows the analysis server to avoid making redundant
15 * calls to "pub list" when nothing has changed.
16 */
17 class OptimizingPubPackageMapInfo extends PackageMapInfo {
18 /**
19 * Map from file path to the file's modification timestamp prior to running
20 * "pub list". Since the set of dependencies is not always known prior to
21 * running "pub list", some or all of the dependencies may be missing from
22 * this map.
23 */
24 final Map<String, int> modificationTimes;
25
26 OptimizingPubPackageMapInfo(Map<String, List<Folder>> packageMap,
27 Set<String> dependencies, this.modificationTimes)
28 : super(packageMap, dependencies);
29
30 /**
31 * Return `true` if the given [path] is listed as a dependency, and we cannot
32 * prove using modification timestamps that it is unchanged.
33 * [resourceProvider] is used (if necessary) to read the [path]'s
34 * modification time.
35 */
36 bool isChangedDependency(String path, ResourceProvider resourceProvider) {
37 if (!dependencies.contains(path)) {
38 // Path is not a dependency.
39 return false;
40 }
41 int lastModificationTime = modificationTimes[path];
42 if (lastModificationTime != null) {
43 Resource resource = resourceProvider.getResource(path);
44 if (resource is File) {
45 try {
46 if (resource.modificationStamp == lastModificationTime) {
47 // Path is a dependency, but it hasn't changed since the last run
48 // of "pub list".
49 return false;
50 }
51 } on FileSystemException {
52 // Path is a dependency, but we can't read its timestamp. Assume
53 // it's changed to be safe.
54 }
55 }
56 }
57 // Path is a dependency, and we couldn't prove that it hadn't changed.
58 // Assume it's changed to be safe.
59 return true;
60 }
61 }
62
63 /**
64 * Extension of [PubPackageMapProvider] that outputs additional information to
65 * allow the analysis server to avoid making redundant calls to "pub list" when
66 * nothing has changed.
67 */
68 class OptimizingPubPackageMapProvider extends PubPackageMapProvider {
69 OptimizingPubPackageMapProvider(
70 ResourceProvider resourceProvider, DirectoryBasedDartSdk sdk, [RunPubList runPubList])
71 : super(resourceProvider, sdk, runPubList);
72
73 /**
74 * Compute a package map for the given folder by executing "pub list". If
75 * [previousInfo] is provided, it is used as a guess of which files the
76 * package map is likely to depend on; the modification times of those files
77 * are captured prior to executing "pub list" so that they can be used to
78 * avoid making redundant calls to "pub list" in the future.
79 *
80 * Also, in the case where dependencies can't be determined because of an
81 * error, the dependencies from [previousInfo] will be preserved.
82 */
83 OptimizingPubPackageMapInfo computePackageMap(Folder folder,
84 [OptimizingPubPackageMapInfo previousInfo]) {
85 // Prior to running "pub list", read the modification timestamps of all of
86 // the old dependencies (if known).
87 Map<String, int> modificationTimes = <String, int>{};
88 if (previousInfo != null) {
89 for (String path in previousInfo.dependencies) {
90 Resource resource = resourceProvider.getResource(path);
91 if (resource is File) {
92 try {
93 modificationTimes[path] = resource.modificationStamp;
94 } on FileSystemException {
95 // File no longer exists. Don't record a timestamp for it; this
96 // will ensure that if the file reappears, we will re-run "pub
97 // list" regardless of the timestamp it reappears with.
98 }
99 }
100 }
101 }
102
103 // Try running "pub list".
104 PackageMapInfo info = super.computePackageMap(folder);
105 if (info == null) {
106 // Computing the package map resulted in an error. Merge the old
107 // dependencies with the new ones, if possible.
108 info = super.computePackageMapError(folder);
109 if (previousInfo != null) {
110 info.dependencies.addAll(previousInfo.dependencies);
111 }
112 }
113
114 // Discard any elements of modificationTimes that are no longer
115 // dependencies.
116 if (previousInfo != null) {
117 for (String dependency
118 in previousInfo.dependencies.difference(info.dependencies)) {
119 modificationTimes.remove(dependency);
120 }
121 }
122
123 // Bundle the modificationTimes with the other info.
124 return new OptimizingPubPackageMapInfo(
125 info.packageMap, info.dependencies, modificationTimes);
126 }
127
128 @override
129 PackageMapInfo computePackageMapError(Folder folder) {
130 // Return null to indicate to our override of computePackageMap that there
131 // was an error, so it can compute dependencies correctly.
132 return null;
133 }
134 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698