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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: pkg/analysis_server/lib/src/source/optimizing_pub_package_map_provider.dart
diff --git a/pkg/analysis_server/lib/src/source/optimizing_pub_package_map_provider.dart b/pkg/analysis_server/lib/src/source/optimizing_pub_package_map_provider.dart
new file mode 100644
index 0000000000000000000000000000000000000000..ccda5f963e9970ddcf275d80077f0b45c693cf31
--- /dev/null
+++ b/pkg/analysis_server/lib/src/source/optimizing_pub_package_map_provider.dart
@@ -0,0 +1,134 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library source.optimizing_pub_package_map_provider;
+
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/source/package_map_provider.dart';
+import 'package:analyzer/source/pub_package_map_provider.dart';
+import 'package:analyzer/src/generated/sdk_io.dart';
+
+/**
+ * Extension of [PackageMapInfo] that tracks the modification timestamps of
+ * pub dependencies. This allows the analysis server to avoid making redundant
+ * calls to "pub list" when nothing has changed.
+ */
+class OptimizingPubPackageMapInfo extends PackageMapInfo {
+ /**
+ * Map from file path to the file's modification timestamp prior to running
+ * "pub list". Since the set of dependencies is not always known prior to
+ * running "pub list", some or all of the dependencies may be missing from
+ * this map.
+ */
+ final Map<String, int> modificationTimes;
+
+ OptimizingPubPackageMapInfo(Map<String, List<Folder>> packageMap,
+ Set<String> dependencies, this.modificationTimes)
+ : super(packageMap, dependencies);
+
+ /**
+ * Return `true` if the given [path] is listed as a dependency, and we cannot
+ * prove using modification timestamps that it is unchanged.
+ * [resourceProvider] is used (if necessary) to read the [path]'s
+ * modification time.
+ */
+ bool isChangedDependency(String path, ResourceProvider resourceProvider) {
+ if (!dependencies.contains(path)) {
+ // Path is not a dependency.
+ return false;
+ }
+ int lastModificationTime = modificationTimes[path];
+ if (lastModificationTime != null) {
+ Resource resource = resourceProvider.getResource(path);
+ if (resource is File) {
+ try {
+ if (resource.modificationStamp == lastModificationTime) {
+ // Path is a dependency, but it hasn't changed since the last run
+ // of "pub list".
+ return false;
+ }
+ } on FileSystemException {
+ // Path is a dependency, but we can't read its timestamp. Assume
+ // it's changed to be safe.
+ }
+ }
+ }
+ // Path is a dependency, and we couldn't prove that it hadn't changed.
+ // Assume it's changed to be safe.
+ return true;
+ }
+}
+
+/**
+ * Extension of [PubPackageMapProvider] that outputs additional information to
+ * allow the analysis server to avoid making redundant calls to "pub list" when
+ * nothing has changed.
+ */
+class OptimizingPubPackageMapProvider extends PubPackageMapProvider {
+ OptimizingPubPackageMapProvider(
+ ResourceProvider resourceProvider, DirectoryBasedDartSdk sdk, [RunPubList runPubList])
+ : super(resourceProvider, sdk, runPubList);
+
+ /**
+ * Compute a package map for the given folder by executing "pub list". If
+ * [previousInfo] is provided, it is used as a guess of which files the
+ * package map is likely to depend on; the modification times of those files
+ * are captured prior to executing "pub list" so that they can be used to
+ * avoid making redundant calls to "pub list" in the future.
+ *
+ * Also, in the case where dependencies can't be determined because of an
+ * error, the dependencies from [previousInfo] will be preserved.
+ */
+ OptimizingPubPackageMapInfo computePackageMap(Folder folder,
+ [OptimizingPubPackageMapInfo previousInfo]) {
+ // Prior to running "pub list", read the modification timestamps of all of
+ // the old dependencies (if known).
+ Map<String, int> modificationTimes = <String, int>{};
+ if (previousInfo != null) {
+ for (String path in previousInfo.dependencies) {
+ Resource resource = resourceProvider.getResource(path);
+ if (resource is File) {
+ try {
+ modificationTimes[path] = resource.modificationStamp;
+ } on FileSystemException {
+ // File no longer exists. Don't record a timestamp for it; this
+ // will ensure that if the file reappears, we will re-run "pub
+ // list" regardless of the timestamp it reappears with.
+ }
+ }
+ }
+ }
+
+ // Try running "pub list".
+ PackageMapInfo info = super.computePackageMap(folder);
+ if (info == null) {
+ // Computing the package map resulted in an error. Merge the old
+ // dependencies with the new ones, if possible.
+ info = super.computePackageMapError(folder);
+ if (previousInfo != null) {
+ info.dependencies.addAll(previousInfo.dependencies);
+ }
+ }
+
+ // Discard any elements of modificationTimes that are no longer
+ // dependencies.
+ if (previousInfo != null) {
+ for (String dependency
+ in previousInfo.dependencies.difference(info.dependencies)) {
+ modificationTimes.remove(dependency);
+ }
+ }
+
+ // Bundle the modificationTimes with the other info.
+ return new OptimizingPubPackageMapInfo(
+ info.packageMap, info.dependencies, modificationTimes);
+ }
+
+ @override
+ PackageMapInfo computePackageMapError(Folder folder) {
+ // Return null to indicate to our override of computePackageMap that there
+ // was an error, so it can compute dependencies correctly.
+ return null;
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698