mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 04:37:12 +00:00
Partially fix the cache invalidation problem during incremental resolution.
It still takes 90% of total incremental resolution time. But at least it's not 10 seconds anymore, just 300ms in Analyzer + Server, or 80ms in pure Analyzer. R=brianwilkerson@google.com BUG= Review URL: https://codereview.chromium.org//1350423002 .
This commit is contained in:
parent
1b9b77d735
commit
14b726f3e6
|
@ -251,6 +251,11 @@ class CacheEntry {
|
|||
*/
|
||||
static int _EXPLICITLY_ADDED_FLAG = 0;
|
||||
|
||||
/**
|
||||
* The next invalidation process identifier.
|
||||
*/
|
||||
static int nextInvalidateId = 0;
|
||||
|
||||
/**
|
||||
* The target this entry is about.
|
||||
*/
|
||||
|
@ -440,7 +445,7 @@ class CacheEntry {
|
|||
if (state == CacheState.INVALID) {
|
||||
ResultData data = _resultMap[descriptor];
|
||||
if (data != null) {
|
||||
_invalidate(descriptor, delta);
|
||||
_invalidate(nextInvalidateId++, descriptor, delta, 0);
|
||||
}
|
||||
} else {
|
||||
ResultData data = getResultData(descriptor);
|
||||
|
@ -490,7 +495,7 @@ class CacheEntry {
|
|||
*/
|
||||
void setValueIncremental(ResultDescriptor descriptor, dynamic value) {
|
||||
ResultData data = getResultData(descriptor);
|
||||
_invalidateDependentResults(data, null);
|
||||
_invalidateDependentResults(null, data, null, 0);
|
||||
data.state = CacheState.VALID;
|
||||
data.value = value;
|
||||
}
|
||||
|
@ -511,25 +516,33 @@ class CacheEntry {
|
|||
* Invalidate the result represented by the given [descriptor] and propagate
|
||||
* invalidation to other results that depend on it.
|
||||
*/
|
||||
void _invalidate(ResultDescriptor descriptor, Delta delta) {
|
||||
void _invalidate(
|
||||
int id, ResultDescriptor descriptor, Delta delta, int level) {
|
||||
ResultData thisData = _resultMap[descriptor];
|
||||
if (thisData == null) {
|
||||
return;
|
||||
}
|
||||
// Stop if already validated.
|
||||
if (delta != null) {
|
||||
if (thisData.invalidateId == id) {
|
||||
return;
|
||||
}
|
||||
thisData.invalidateId = id;
|
||||
}
|
||||
// Ask the delta to validate.
|
||||
DeltaResult deltaResult = null;
|
||||
if (delta != null) {
|
||||
deltaResult = delta.validate(_partition.context, target, descriptor);
|
||||
if (deltaResult == DeltaResult.STOP) {
|
||||
// print('not-invalidate $descriptor for $target');
|
||||
return;
|
||||
}
|
||||
}
|
||||
// print('invalidate $descriptor for $target');
|
||||
ResultData thisData;
|
||||
if (deltaResult == null || deltaResult == DeltaResult.INVALIDATE) {
|
||||
thisData = _resultMap.remove(descriptor);
|
||||
}
|
||||
if (deltaResult == DeltaResult.KEEP_CONTINUE) {
|
||||
thisData = _resultMap[descriptor];
|
||||
}
|
||||
if (thisData == null) {
|
||||
return;
|
||||
_resultMap.remove(descriptor);
|
||||
// {
|
||||
// String indent = ' ' * level;
|
||||
// print('[$id]$indent invalidate $descriptor for $target');
|
||||
// }
|
||||
}
|
||||
// Stop depending on other results.
|
||||
TargetedResult thisResult = new TargetedResult(target, descriptor);
|
||||
|
@ -540,7 +553,7 @@ class CacheEntry {
|
|||
}
|
||||
}
|
||||
// Invalidate results that depend on this result.
|
||||
_invalidateDependentResults(thisData, delta);
|
||||
_invalidateDependentResults(id, thisData, delta, level + 1);
|
||||
// If empty, remove the entry altogether.
|
||||
if (_resultMap.isEmpty) {
|
||||
_partition._targetMap.remove(target);
|
||||
|
@ -557,19 +570,20 @@ class CacheEntry {
|
|||
void _invalidateAll() {
|
||||
List<ResultDescriptor> results = _resultMap.keys.toList();
|
||||
for (ResultDescriptor result in results) {
|
||||
_invalidate(result, null);
|
||||
_invalidate(null, result, null, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate results that depend on [thisData].
|
||||
*/
|
||||
void _invalidateDependentResults(ResultData thisData, Delta delta) {
|
||||
void _invalidateDependentResults(
|
||||
int id, ResultData thisData, Delta delta, int level) {
|
||||
List<TargetedResult> dependentResults = thisData.dependentResults.toList();
|
||||
for (TargetedResult dependentResult in dependentResults) {
|
||||
CacheEntry entry = _partition.get(dependentResult.target);
|
||||
if (entry != null) {
|
||||
entry._invalidate(dependentResult.result, delta);
|
||||
entry._invalidate(id, dependentResult.result, delta, level);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1099,6 +1113,13 @@ class ResultData {
|
|||
*/
|
||||
Object value;
|
||||
|
||||
/**
|
||||
* The identifier of the invalidation process that most recently checked
|
||||
* this value. If it is the same as the current invalidation identifier,
|
||||
* then there is no reason to check it (and its subtree again).
|
||||
*/
|
||||
int invalidateId = -1;
|
||||
|
||||
/**
|
||||
* A list of the results on which this result depends.
|
||||
*/
|
||||
|
|
|
@ -864,6 +864,22 @@ class IncrementalBodyDelta extends Delta {
|
|||
if (descriptor == CONTENT) {
|
||||
return DeltaResult.KEEP_CONTINUE;
|
||||
}
|
||||
if (target is Source && target != source) {
|
||||
if (isByTask(DartErrorsTask.DESCRIPTOR) ||
|
||||
isByTask(LibraryErrorsReadyTask.DESCRIPTOR)) {
|
||||
return DeltaResult.KEEP_CONTINUE;
|
||||
}
|
||||
}
|
||||
if (target is LibrarySpecificUnit &&
|
||||
target.unit != source &&
|
||||
target.library != source) {
|
||||
if (isByTask(GatherUsedLocalElementsTask.DESCRIPTOR) ||
|
||||
isByTask(GatherUsedImportedElementsTask.DESCRIPTOR) ||
|
||||
isByTask(GenerateHintsTask.DESCRIPTOR) ||
|
||||
isByTask(LibraryUnitErrorsTask.DESCRIPTOR)) {
|
||||
return DeltaResult.KEEP_CONTINUE;
|
||||
}
|
||||
}
|
||||
if (isByTask(BuildCompilationUnitElementTask.DESCRIPTOR) ||
|
||||
isByTask(BuildDirectiveElementsTask.DESCRIPTOR) ||
|
||||
isByTask(BuildEnumMemberElementsTask.DESCRIPTOR) ||
|
||||
|
@ -1247,9 +1263,14 @@ class IncrementalResolver {
|
|||
|
||||
void _updateCache() {
|
||||
if (newSourceEntry != null) {
|
||||
newSourceEntry.setState(CONTENT, CacheState.INVALID,
|
||||
delta: new IncrementalBodyDelta(_source, _updateOffset, _updateEndOld,
|
||||
_updateEndNew, _updateDelta));
|
||||
LoggingTimer timer = logger.startTimer();
|
||||
try {
|
||||
newSourceEntry.setState(CONTENT, CacheState.INVALID,
|
||||
delta: new IncrementalBodyDelta(_source, _updateOffset,
|
||||
_updateEndOld, _updateEndNew, _updateDelta));
|
||||
} finally {
|
||||
timer.stop('invalidate cache with delta');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue