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

Side by Side Diff: pkg/analyzer/lib/src/summary/incremental_cache.dart

Issue 1818823005: Cache library closure hashes and absolute URIs. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 9 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
« 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:convert' show UTF8; 5 import 'dart:convert' show UTF8;
6 import 'dart:core' hide Resource; 6 import 'dart:core' hide Resource;
7 7
8 import 'package:analyzer/dart/element/element.dart'; 8 import 'package:analyzer/dart/element/element.dart';
9 import 'package:analyzer/file_system/file_system.dart';
10 import 'package:analyzer/src/generated/engine.dart'; 9 import 'package:analyzer/src/generated/engine.dart';
11 import 'package:analyzer/src/generated/source.dart'; 10 import 'package:analyzer/src/generated/source.dart';
12 import 'package:analyzer/src/summary/format.dart'; 11 import 'package:analyzer/src/summary/format.dart';
13 import 'package:analyzer/src/summary/idl.dart'; 12 import 'package:analyzer/src/summary/idl.dart';
14 import 'package:analyzer/src/summary/summarize_elements.dart'; 13 import 'package:analyzer/src/summary/summarize_elements.dart';
15 import 'package:crypto/crypto.dart'; 14 import 'package:crypto/crypto.dart';
16 15
17 /** 16 /**
18 * Storage for cache data. 17 * Storage for cache data.
19 */ 18 */
(...skipping 10 matching lines...) Expand all
30 * Otherwise the key-value pair is added to the storage. 29 * Otherwise the key-value pair is added to the storage.
31 * 30 *
32 * It is not guaranteed that data will always be accessible using [get], in 31 * It is not guaranteed that data will always be accessible using [get], in
33 * some implementations association may silently fail or become inaccessible 32 * some implementations association may silently fail or become inaccessible
34 * after some time. 33 * after some time.
35 */ 34 */
36 void put(String key, List<int> bytes); 35 void put(String key, List<int> bytes);
37 } 36 }
38 37
39 /** 38 /**
40 * A [Folder] based implementation of [CacheStorage].
41 */
42 class FolderCacheStorage implements CacheStorage {
Paul Berry 2016/03/21 20:29:32 I'm not sure I agree with the idea of removing thi
scheglov 2016/03/21 20:58:26 OK, restored.
43 /**
44 * The folder to read and write files.
45 */
46 final Folder folder;
47
48 /**
49 * To ensure that operations of writing files are atomic we create a temporary
50 * file with this name in the [folder] and then rename it once we are
51 * done writing.
52 */
53 final String tempFileName;
54
55 FolderCacheStorage(this.folder, this.tempFileName);
56
57 @override
58 List<int> get(String key) {
59 Resource file = folder.getChild(key);
60 if (file is File) {
61 try {
62 return file.readAsBytesSync();
63 } on FileSystemException {}
64 }
65 return null;
66 }
67
68 @override
69 void put(String key, List<int> bytes) {
70 String absPath = folder.getChild(key).path;
71 File tempFile = folder.getChild(tempFileName);
72 tempFile.writeAsBytesSync(bytes);
73 try {
74 tempFile.renameSync(absPath);
75 } catch (e) {}
76 }
77 }
78
79 /**
80 * Cache of information to support incremental analysis. 39 * Cache of information to support incremental analysis.
81 * 40 *
82 * Note that currently this class is not intended for interactive use. 41 * Note that currently this class is not intended for interactive use.
83 */ 42 */
84 class IncrementalCache { 43 class IncrementalCache {
85 /** 44 /**
86 * The storage for the cache data. 45 * The storage for the cache data.
87 */ 46 */
88 final CacheStorage storage; 47 final CacheStorage storage;
89 48
90 /** 49 /**
91 * The context in which this cache is used. 50 * The context in which this cache is used.
92 */ 51 */
93 final AnalysisContext context; 52 final AnalysisContext context;
94 53
95 /** 54 /**
96 * Opaque data that reflects the current configuration, such as the [context] 55 * Opaque data that reflects the current configuration, such as the [context]
97 * options, and is mixed into the hashes. 56 * options, and is mixed into the hashes.
98 */ 57 */
99 final List<int> configSalt; 58 final List<int> configSalt;
100 59
101 final Map<Source, CacheSourceContent> _sourceContentMap = 60 final Map<Source, CacheSourceContent> _sourceContentMap =
102 <Source, CacheSourceContent>{}; 61 <Source, CacheSourceContent>{};
103 final Map<Source, List<Source>> _libraryClosureMap = <Source, List<Source>>{}; 62 final Map<Source, List<Source>> _libraryClosureMap = <Source, List<Source>>{};
63 final Map<Source, List<int>> _libraryClosureHashMap = <Source, List<int>>{};
104 final Map<Source, List<int>> _sourceContentHashMap = <Source, List<int>>{}; 64 final Map<Source, List<int>> _sourceContentHashMap = <Source, List<int>>{};
105 65
106 /** 66 /**
107 * Mapping from a library closure key to its [PackageBundle]. 67 * Mapping from a library closure key to its [PackageBundle].
108 */ 68 */
109 final Map<String, PackageBundle> _bundleMap = <String, PackageBundle>{}; 69 final Map<String, PackageBundle> _bundleMap = <String, PackageBundle>{};
110 70
71 final Map<String, Source> _absoluteUriMap = <String, Source>{};
72
111 IncrementalCache(this.storage, this.context, this.configSalt); 73 IncrementalCache(this.storage, this.context, this.configSalt);
112 74
113 /** 75 /**
114 * Clear internal caches so that we read from file system again. 76 * Clear internal caches so that we read from file system again.
115 */ 77 */
116 void clearInternalCaches() { 78 void clearInternalCaches() {
117 _sourceContentMap.clear(); 79 _sourceContentMap.clear();
118 _libraryClosureMap.clear(); 80 _libraryClosureMap.clear();
119 _sourceContentHashMap.clear(); 81 _sourceContentHashMap.clear();
120 _bundleMap.clear(); 82 _bundleMap.clear();
(...skipping 10 matching lines...) Expand all
131 * using [LibraryBundleWithId.id]. 93 * using [LibraryBundleWithId.id].
132 */ 94 */
133 List<LibraryBundleWithId> getLibraryClosureBundles(Source librarySource) { 95 List<LibraryBundleWithId> getLibraryClosureBundles(Source librarySource) {
134 try { 96 try {
135 List<Source> closureSources = _getLibraryClosure(librarySource); 97 List<Source> closureSources = _getLibraryClosure(librarySource);
136 List<LibraryBundleWithId> closureBundles = <LibraryBundleWithId>[]; 98 List<LibraryBundleWithId> closureBundles = <LibraryBundleWithId>[];
137 for (Source source in closureSources) { 99 for (Source source in closureSources) {
138 if (source.isInSystemLibrary) { 100 if (source.isInSystemLibrary) {
139 continue; 101 continue;
140 } 102 }
103 if (getSourceKind(source) == SourceKind.PART) {
104 continue;
105 }
141 String key = _getLibraryBundleKey(source); 106 String key = _getLibraryBundleKey(source);
142 PackageBundle bundle = _getLibraryBundle(key); 107 PackageBundle bundle = _getLibraryBundle(key);
143 if (bundle == null) { 108 if (bundle == null) {
144 return null; 109 return null;
145 } 110 }
146 closureBundles.add(new LibraryBundleWithId(source, key, bundle)); 111 closureBundles.add(new LibraryBundleWithId(source, key, bundle));
147 } 112 }
148 return closureBundles; 113 return closureBundles;
149 } catch (e) { 114 } catch (e) {
150 return null; 115 return null;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 * all its directly or indirectly imported or exported libraries. 152 * all its directly or indirectly imported or exported libraries.
188 */ 153 */
189 void _appendLibraryClosure(Set<Source> closure, Source librarySource) { 154 void _appendLibraryClosure(Set<Source> closure, Source librarySource) {
190 if (closure.add(librarySource)) { 155 if (closure.add(librarySource)) {
191 CacheSourceContent contentSource = _getCacheSourceContent(librarySource); 156 CacheSourceContent contentSource = _getCacheSourceContent(librarySource);
192 if (contentSource == null) { 157 if (contentSource == null) {
193 throw new StateError('No structure for $librarySource'); 158 throw new StateError('No structure for $librarySource');
194 } 159 }
195 // Append parts. 160 // Append parts.
196 for (String partUri in contentSource.partUris) { 161 for (String partUri in contentSource.partUris) {
197 Source partSource = 162 Source partSource = _resolveUri(librarySource, partUri);
198 context.sourceFactory.resolveUri(librarySource, partUri);
199 if (partSource == null) { 163 if (partSource == null) {
200 throw new StateError('Unable to resolve $partUri in $librarySource'); 164 throw new StateError('Unable to resolve $partUri in $librarySource');
201 } 165 }
202 closure.add(partSource); 166 closure.add(partSource);
203 } 167 }
204 // Append imports and exports. 168 // Append imports and exports.
205 void appendLibrarySources(String refUri) { 169 void appendLibrarySources(String refUri) {
206 Source refSource = 170 Source refSource = _resolveUri(librarySource, refUri);
207 context.sourceFactory.resolveUri(librarySource, refUri);
208 if (refSource == null) { 171 if (refSource == null) {
209 throw new StateError('Unable to resolve $refUri in $librarySource'); 172 throw new StateError('Unable to resolve $refUri in $librarySource');
210 } 173 }
211 _appendLibraryClosure(closure, refSource); 174 _appendLibraryClosure(closure, refSource);
212 } 175 }
213 contentSource.importedUris.forEach(appendLibrarySources); 176 contentSource.importedUris.forEach(appendLibrarySources);
214 contentSource.exportedUris.forEach(appendLibrarySources); 177 contentSource.exportedUris.forEach(appendLibrarySources);
215 } 178 }
216 } 179 }
217 180
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
278 _appendLibraryClosure(closure, librarySource); 241 _appendLibraryClosure(closure, librarySource);
279 return closure.toList(); 242 return closure.toList();
280 }); 243 });
281 } 244 }
282 245
283 /** 246 /**
284 * Return the [context]-specific hash of the closure of the library with 247 * Return the [context]-specific hash of the closure of the library with
285 * the given [librarySource]. 248 * the given [librarySource].
286 */ 249 */
287 List<int> _getLibraryClosureHash(Source librarySource) { 250 List<int> _getLibraryClosureHash(Source librarySource) {
288 List<Source> closure = _getLibraryClosure(librarySource); 251 return _libraryClosureHashMap.putIfAbsent(librarySource, () {
289 MD5 md5 = new MD5(); 252 List<Source> closure = _getLibraryClosure(librarySource);
290 for (Source source in closure) { 253 MD5 md5 = new MD5();
291 List<int> sourceHash = _getSourceContentHash(source); 254 for (Source source in closure) {
292 md5.add(sourceHash); 255 List<int> sourceHash = _getSourceContentHash(source);
293 } 256 md5.add(sourceHash);
294 md5.add(configSalt); 257 }
295 return md5.close(); 258 md5.add(configSalt);
259 return md5.close();
260 });
296 } 261 }
297 262
298 /** 263 /**
299 * Compute a hash of the given [source] contents. 264 * Compute a hash of the given [source] contents.
300 */ 265 */
301 List<int> _getSourceContentHash(Source source) { 266 List<int> _getSourceContentHash(Source source) {
302 return _sourceContentHashMap.putIfAbsent(source, () { 267 return _sourceContentHashMap.putIfAbsent(source, () {
303 String sourceText = source.contents.data; 268 String sourceText = source.contents.data;
304 List<int> sourceBytes = UTF8.encode(sourceText); 269 List<int> sourceBytes = UTF8.encode(sourceText);
305 return (new MD5()..add(sourceBytes)).close(); 270 return (new MD5()..add(sourceBytes)).close();
306 }); 271 });
307 } 272 }
308 273
309 /** 274 /**
275 * Return a source representing the URI that results from resolving the given
276 * (possibly relative) [containedUri] against the URI associated with the
277 * [containingSource], whether or not the resulting source exists, or `null`
278 * if either the [containedUri] is invalid or if it cannot be resolved against
279 * the [containingSource]'s URI.
280 */
281 Source _resolveUri(Source containingSource, String containedUri) {
282 // Cache absolute URIs.
283 if (containedUri.startsWith('dart:') ||
Paul Berry 2016/03/21 20:29:32 If the goal is to figure out whether this is an ab
scheglov 2016/03/21 20:58:26 See the performance results in mail. URI operation
284 containedUri.startsWith('package:')) {
285 return _absoluteUriMap.putIfAbsent(containedUri, () {
286 return context.sourceFactory.resolveUri(containingSource, containedUri);
287 });
288 }
289 // Resolve relative URIs without caching.
290 return context.sourceFactory.resolveUri(containingSource, containedUri);
291 }
292
293 /**
310 * Write the content based information about the given [source]. 294 * Write the content based information about the given [source].
311 */ 295 */
312 void _writeCacheSourceContent(Source source, CacheSourceContentBuilder b) { 296 void _writeCacheSourceContent(Source source, CacheSourceContentBuilder b) {
313 String key = _getCacheSourceContentKey(source); 297 String key = _getCacheSourceContentKey(source);
314 List<int> bytes = b.toBuffer(); 298 List<int> bytes = b.toBuffer();
315 storage.put(key, bytes); 299 storage.put(key, bytes);
316 // Put into the cache to avoid reading it later. 300 // Put into the cache to avoid reading it later.
317 _sourceContentMap[source] = new CacheSourceContent.fromBuffer(bytes); 301 _sourceContentMap[source] = new CacheSourceContent.fromBuffer(bytes);
318 } 302 }
319 303
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
386 */ 370 */
387 final String id; 371 final String id;
388 372
389 /** 373 /**
390 * The payload bundle. 374 * The payload bundle.
391 */ 375 */
392 final PackageBundle bundle; 376 final PackageBundle bundle;
393 377
394 LibraryBundleWithId(this.source, this.id, this.bundle); 378 LibraryBundleWithId(this.source, this.id, this.bundle);
395 } 379 }
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