mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 23:39:48 +00:00
Modify FileResolver / bytestore to keep track of invalidated cache elements.
Change-Id: I60cb1f5f04eb9a1ee34c50157d5ed2da92d408ec Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/167861 Commit-Queue: Keerti Parthasarathy <keertip@google.com> Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
parent
5a28f14a25
commit
fdad84fa5b
|
@ -5,6 +5,13 @@
|
|||
import 'package:analyzer/src/dart/analysis/cache.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
|
||||
class CacheData {
|
||||
final int id;
|
||||
final List<int> bytes;
|
||||
|
||||
CacheData(this.id, this.bytes);
|
||||
}
|
||||
|
||||
/// Store of bytes associated with string keys and a hash.
|
||||
///
|
||||
/// Each key must be not longer than 100 characters and consist of only `[a-z]`,
|
||||
|
@ -18,39 +25,52 @@ abstract class CiderByteStore {
|
|||
/// [signature].
|
||||
///
|
||||
/// Return `null` if the association does not exist.
|
||||
List<int> get(String key, List<int> signature);
|
||||
CacheData get(String key, List<int> signature);
|
||||
|
||||
/// Associate the given [bytes] with the [key] and [digest].
|
||||
void put(String key, List<int> signature, List<int> bytes);
|
||||
/// Associate the given [bytes] with the [key] and [signature]. Return the
|
||||
/// [CacheData].
|
||||
CacheData putGet(String key, List<int> signature, List<int> bytes);
|
||||
|
||||
/// Used to decrement reference count for the given ids, if implemented.
|
||||
void release(Iterable<int> ids);
|
||||
}
|
||||
|
||||
class CiderCachedByteStore implements CiderByteStore {
|
||||
final Cache<String, CiderCacheEntry> _cache;
|
||||
int idCounter = 0;
|
||||
|
||||
CiderCachedByteStore(int maxCacheSize)
|
||||
: _cache =
|
||||
Cache<String, CiderCacheEntry>(maxCacheSize, (v) => v.bytes.length);
|
||||
: _cache = Cache<String, CiderCacheEntry>(
|
||||
maxCacheSize, (v) => v.data.bytes.length);
|
||||
|
||||
@override
|
||||
List<int> get(String key, List<int> signature) {
|
||||
CacheData get(String key, List<int> signature) {
|
||||
var entry = _cache.get(key, () => null);
|
||||
|
||||
if (entry != null &&
|
||||
const ListEquality<int>().equals(entry.signature, signature)) {
|
||||
return entry.bytes;
|
||||
return entry.data;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
void put(String key, List<int> signature, List<int> bytes) {
|
||||
_cache.put(key, CiderCacheEntry(signature, bytes));
|
||||
CacheData putGet(String key, List<int> signature, List<int> bytes) {
|
||||
idCounter++;
|
||||
var entry = CiderCacheEntry(signature, CacheData(idCounter, bytes));
|
||||
_cache.put(key, entry);
|
||||
return entry.data;
|
||||
}
|
||||
|
||||
@override
|
||||
void release(Iterable<int> ids) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
class CiderCacheEntry {
|
||||
final CacheData data;
|
||||
final List<int> signature;
|
||||
final List<int> bytes;
|
||||
|
||||
CiderCacheEntry(this.signature, this.bytes);
|
||||
CiderCacheEntry(this.signature, this.data);
|
||||
}
|
||||
|
|
|
@ -90,6 +90,9 @@ class FileState {
|
|||
UnlinkedUnit2 unlinked2;
|
||||
LibraryCycle _libraryCycle;
|
||||
|
||||
/// id of the cache entry.
|
||||
int id;
|
||||
|
||||
FileState._(
|
||||
this._fsState,
|
||||
this.path,
|
||||
|
@ -219,7 +222,8 @@ class FileState {
|
|||
// Prepare bytes of the unlinked bundle - existing or new.
|
||||
List<int> bytes;
|
||||
{
|
||||
bytes = _fsState._byteStore.get(unlinkedKey, _digest);
|
||||
var cacheData = _fsState._byteStore.get(unlinkedKey, _digest);
|
||||
bytes = cacheData?.bytes;
|
||||
|
||||
if (bytes == null || bytes.isEmpty) {
|
||||
var content = performance.run('content', (_) {
|
||||
|
@ -236,7 +240,8 @@ class FileState {
|
|||
var unlinkedBuilder = serializeAstCiderUnlinked(_digest, unit);
|
||||
bytes = unlinkedBuilder.toBuffer();
|
||||
performance.getDataInt('length').add(bytes.length);
|
||||
_fsState._byteStore.put(unlinkedKey, _digest, bytes);
|
||||
cacheData = _fsState._byteStore.putGet(unlinkedKey, _digest, bytes);
|
||||
bytes = cacheData.bytes;
|
||||
});
|
||||
|
||||
performance.run('prefetch', (_) {
|
||||
|
@ -244,6 +249,7 @@ class FileState {
|
|||
_prefetchDirectReferences(unlinked2);
|
||||
});
|
||||
}
|
||||
id = cacheData.id;
|
||||
}
|
||||
|
||||
// Read the unlinked bundle.
|
||||
|
@ -645,6 +651,9 @@ class LibraryCycle {
|
|||
/// The hash of all the paths of the files in this cycle.
|
||||
String cyclePathsHash;
|
||||
|
||||
/// id of the cache entry.
|
||||
int id;
|
||||
|
||||
LibraryCycle();
|
||||
|
||||
String get signatureStr {
|
||||
|
|
|
@ -83,6 +83,11 @@ class FileResolver {
|
|||
|
||||
_LibraryContext libraryContext;
|
||||
|
||||
/// List of ids for cache elements that are invalidated. Track elements that
|
||||
/// are invalidated during [changeFile]. Used in [releaseAndClearRemovedIds] to
|
||||
/// release the cache items and is then cleared.
|
||||
final Set<int> removedCacheIds = {};
|
||||
|
||||
FileResolver(
|
||||
PerformanceLog logger,
|
||||
ResourceProvider resourceProvider,
|
||||
|
@ -132,7 +137,8 @@ class FileResolver {
|
|||
/// Update the resolver to reflect the fact that the file with the given
|
||||
/// [path] was changed. We need to make sure that when this file, of any file
|
||||
/// that directly or indirectly referenced it, is resolved, we used the new
|
||||
/// state of the file.
|
||||
/// state of the file. Updates [removedCacheIds] with the ids of the invalidated
|
||||
/// items, used in [releaseAndClearRemovedIds] to release the cache items.
|
||||
void changeFile(String path) {
|
||||
if (fsState == null) {
|
||||
return;
|
||||
|
@ -149,12 +155,13 @@ class FileResolver {
|
|||
path: removedFile.path,
|
||||
uri: removedFile.uri,
|
||||
);
|
||||
removedCacheIds.add(removedFile.id);
|
||||
}
|
||||
|
||||
// Remove libraries represented by removed files.
|
||||
// If we need these libraries later, we will relink and reattach them.
|
||||
if (libraryContext != null) {
|
||||
libraryContext.remove(removedFiles);
|
||||
libraryContext.remove(removedFiles, removedCacheIds);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -184,7 +191,7 @@ class FileResolver {
|
|||
var errorsSignature = errorsSignatureBuilder.toByteList();
|
||||
|
||||
var errorsKey = file.path + '.errors';
|
||||
var bytes = byteStore.get(errorsKey, errorsSignature);
|
||||
var bytes = byteStore.get(errorsKey, errorsSignature)?.bytes;
|
||||
List<AnalysisError> errors;
|
||||
if (bytes != null) {
|
||||
var data = CiderUnitErrors.fromBuffer(bytes);
|
||||
|
@ -204,7 +211,7 @@ class FileResolver {
|
|||
signature: errorsSignature,
|
||||
errors: errors.map(ErrorEncoding.encode).toList(),
|
||||
).toBuffer();
|
||||
byteStore.put(errorsKey, errorsSignature, bytes);
|
||||
bytes = byteStore.putGet(errorsKey, errorsSignature, bytes).bytes;
|
||||
}
|
||||
|
||||
return ErrorsResultImpl(
|
||||
|
@ -314,6 +321,12 @@ class FileResolver {
|
|||
_resetContextObjects();
|
||||
}
|
||||
|
||||
/// Update the cache with list of invalidated ids and clears [removedCacheIds].
|
||||
void releaseAndClearRemovedIds() {
|
||||
byteStore.release(removedCacheIds);
|
||||
removedCacheIds.clear();
|
||||
}
|
||||
|
||||
/// The [completionLine] and [completionColumn] are zero based.
|
||||
ResolvedUnitResult resolve({
|
||||
int completionLine,
|
||||
|
@ -680,7 +693,8 @@ class _LibraryContext {
|
|||
cycle.directDependencies.forEach(loadBundle);
|
||||
|
||||
var key = cycle.cyclePathsHash;
|
||||
var bytes = byteStore.get(key, cycle.signature);
|
||||
var data = byteStore.get(key, cycle.signature);
|
||||
var bytes = data?.bytes;
|
||||
|
||||
if (bytes == null) {
|
||||
librariesLinkedTimer.start();
|
||||
|
@ -732,7 +746,8 @@ class _LibraryContext {
|
|||
|
||||
bytes = serializeBundle(cycle.signature, linkResult).toBuffer();
|
||||
|
||||
byteStore.put(key, cycle.signature, bytes);
|
||||
data = byteStore.putGet(key, cycle.signature, bytes);
|
||||
bytes = data.bytes;
|
||||
performance.getDataInt('bytesPut').add(bytes.length);
|
||||
|
||||
librariesLinkedTimer.stop();
|
||||
|
@ -740,6 +755,7 @@ class _LibraryContext {
|
|||
performance.getDataInt('bytesGet').add(bytes.length);
|
||||
performance.getDataInt('libraryLoadCount').add(cycle.libraries.length);
|
||||
}
|
||||
cycle.id = data.id;
|
||||
|
||||
var cBundle = CiderLinkedLibraryCycle.fromBuffer(bytes);
|
||||
inputBundles.add(cBundle.bundle);
|
||||
|
@ -775,14 +791,18 @@ class _LibraryContext {
|
|||
|
||||
/// Remove libraries represented by the [removed] files.
|
||||
/// If we need these libraries later, we will relink and reattach them.
|
||||
void remove(List<FileState> removed) {
|
||||
void remove(List<FileState> removed, Set<int> removedIds) {
|
||||
elementFactory.removeLibraries(
|
||||
removed.map((e) => e.uriStr).toSet(),
|
||||
);
|
||||
|
||||
var removedSet = removed.toSet();
|
||||
loadedBundles.removeWhere((cycle) {
|
||||
return cycle.libraries.any(removedSet.contains);
|
||||
if (cycle.libraries.any(removedSet.contains)) {
|
||||
removedIds.add(cycle.id);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue