Skip to content

Commit f91547d

Browse files
scheglovcommit-bot@chromium.org
authored andcommitted
Separate signatures for linked elements from signatures for resolution.
So, lints and error filters don't affect cache keys for summaries, and we can reuse them more often across analysis contexts. This makes `dart flutter_tools/bin/flutter_tools.dart analyze --flutter-repo` about 35% faster, from 153 seconds to 113 seconds. Change-Id: I606acce7ef712450783c75d24bc52fd5877b3f1f Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/152725 Commit-Queue: Konstantin Shcheglov <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]>
1 parent 871f0ee commit f91547d

File tree

7 files changed

+180
-39
lines changed

7 files changed

+180
-39
lines changed

pkg/analyzer/lib/src/dart/analysis/driver.dart

Lines changed: 44 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ typedef WorkToWaitAfterComputingResult = Future<void> Function(String path);
9191
/// TODO(scheglov) Clean up the list of implicitly analyzed files.
9292
class AnalysisDriver implements AnalysisDriverGeneric {
9393
/// The version of data format, should be incremented on every format change.
94-
static const int DATA_VERSION = 103;
94+
static const int DATA_VERSION = 104;
9595

9696
/// The length of the list returned by [_computeDeclaredVariablesSignature].
9797
static const int _declaredVariablesSignatureLength = 4;
@@ -144,12 +144,18 @@ class AnalysisDriver implements AnalysisDriverGeneric {
144144
api.AnalysisContext analysisContext;
145145

146146
/// The salt to mix into all hashes used as keys for unlinked data.
147-
final Uint32List _unlinkedSalt =
148-
Uint32List(2 + AnalysisOptionsImpl.unlinkedSignatureLength);
147+
final Uint32List _saltForUnlinked =
148+
Uint32List(2 + AnalysisOptionsImpl.signatureLength);
149+
150+
/// The salt to mix into all hashes used as keys for elements.
151+
final Uint32List _saltForElements = Uint32List(1 +
152+
AnalysisOptionsImpl.signatureLength +
153+
_declaredVariablesSignatureLength);
149154

150155
/// The salt to mix into all hashes used as keys for linked data.
151-
final Uint32List _linkedSalt = Uint32List(
152-
2 + AnalysisOptions.signatureLength + _declaredVariablesSignatureLength);
156+
final Uint32List _saltForResolution = Uint32List(2 +
157+
AnalysisOptionsImpl.signatureLength +
158+
_declaredVariablesSignatureLength);
153159

154160
/// The set of priority files, that should be analyzed sooner.
155161
final _priorityFiles = <String>{};
@@ -860,7 +866,7 @@ class AnalysisDriver implements AnalysisDriverGeneric {
860866
_throwIfNotAbsolutePath(path);
861867
var file = fsState.getFileForPath(path);
862868
ApiSignature signature = ApiSignature();
863-
signature.addUint32List(_linkedSalt);
869+
signature.addUint32List(_saltForResolution);
864870
signature.addString(file.transitiveSignature);
865871
return signature;
866872
}
@@ -1461,8 +1467,8 @@ class AnalysisDriver implements AnalysisDriverGeneric {
14611467
sourceFactory,
14621468
analysisOptions,
14631469
declaredVariables,
1464-
_unlinkedSalt,
1465-
_linkedSalt,
1470+
_saltForUnlinked,
1471+
_saltForElements,
14661472
featureSetProvider,
14671473
externalSummaries: _externalSummaries,
14681474
);
@@ -1480,6 +1486,7 @@ class AnalysisDriver implements AnalysisDriverGeneric {
14801486
NullSafetyUnderstandingFlag.enableNullSafetyTypes(() {
14811487
if (_libraryContext == null) {
14821488
_libraryContext = LibraryContext(
1489+
testView: _testView.libraryContext,
14831490
session: currentSession,
14841491
logger: _logger,
14851492
byteStore: _byteStore,
@@ -1511,31 +1518,47 @@ class AnalysisDriver implements AnalysisDriverGeneric {
15111518
_discoverAvailableFilesTask ??= _DiscoverAvailableFilesTask(this);
15121519
}
15131520

1514-
/// Fill [_unlinkedSalt] and [_linkedSalt] with data.
15151521
void _fillSalt() {
1516-
_unlinkedSalt[0] = DATA_VERSION;
1517-
_unlinkedSalt[1] = enableIndex ? 1 : 0;
1518-
_unlinkedSalt.setAll(2, _analysisOptions.unlinkedSignature);
1522+
_fillSaltForUnlinked();
1523+
_fillSaltForElements();
1524+
_fillSaltForResolution();
1525+
}
1526+
1527+
void _fillSaltForElements() {
1528+
var index = 0;
1529+
1530+
_saltForElements[index] = DATA_VERSION;
1531+
index++;
1532+
1533+
_saltForElements.setAll(index, _analysisOptions.signatureForElements);
1534+
index += AnalysisOptionsImpl.signatureLength;
15191535

1520-
_fillSaltLinked();
1536+
_saltForResolution.setAll(index, _computeDeclaredVariablesSignature());
1537+
index += _declaredVariablesSignatureLength;
15211538
}
15221539

1523-
void _fillSaltLinked() {
1540+
void _fillSaltForResolution() {
15241541
var index = 0;
15251542

1526-
_linkedSalt[index] = DATA_VERSION;
1543+
_saltForResolution[index] = DATA_VERSION;
15271544
index++;
15281545

1529-
_linkedSalt[index] = enableIndex ? 1 : 0;
1546+
_saltForResolution[index] = enableIndex ? 1 : 0;
15301547
index++;
15311548

1532-
_linkedSalt.setAll(index, _analysisOptions.signature);
1533-
index += AnalysisOptionsImpl.unlinkedSignatureLength;
1549+
_saltForResolution.setAll(index, _analysisOptions.signature);
1550+
index += AnalysisOptionsImpl.signatureLength;
15341551

1535-
_linkedSalt.setAll(index, _computeDeclaredVariablesSignature());
1552+
_saltForResolution.setAll(index, _computeDeclaredVariablesSignature());
15361553
index += _declaredVariablesSignatureLength;
15371554
}
15381555

1556+
void _fillSaltForUnlinked() {
1557+
_saltForUnlinked[0] = DATA_VERSION;
1558+
_saltForUnlinked[1] = enableIndex ? 1 : 0;
1559+
_saltForUnlinked.setAll(2, _analysisOptions.unlinkedSignature);
1560+
}
1561+
15391562
/// Load the [AnalysisResult] for the given [file] from the [bytes]. Set
15401563
/// optional [content] and [resolvedUnit].
15411564
AnalysisResult _getAnalysisResultFromBytes(
@@ -1580,7 +1603,7 @@ class AnalysisDriver implements AnalysisDriverGeneric {
15801603
/// in the [library], e.g. element model, errors, index, etc.
15811604
String _getResolvedUnitSignature(FileState library, FileState file) {
15821605
ApiSignature signature = ApiSignature();
1583-
signature.addUint32List(_linkedSalt);
1606+
signature.addUint32List(_saltForResolution);
15841607
signature.addString(library.transitiveSignature);
15851608
signature.addString(file.contentHash);
15861609
return signature.toHex();
@@ -1949,6 +1972,7 @@ class AnalysisDriverScheduler {
19491972
@visibleForTesting
19501973
class AnalysisDriverTestView {
19511974
final AnalysisDriver driver;
1975+
final LibraryContextTestView libraryContext = LibraryContextTestView();
19521976

19531977
int numOfAnalyzedLibraries = 0;
19541978

pkg/analyzer/lib/src/dart/analysis/file_state.dart

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ class FileState {
246246
}
247247

248248
if (_libraryCycle == null) {
249-
computeLibraryCycle(_fsState._linkedSalt, this);
249+
computeLibraryCycle(_fsState._saltForElements, this);
250250
}
251251

252252
return _libraryCycle;
@@ -362,7 +362,7 @@ class FileState {
362362
List<int> contentSignature;
363363
{
364364
var signature = ApiSignature();
365-
signature.addUint32List(_fsState._unlinkedSalt);
365+
signature.addUint32List(_fsState._saltForUnlinked);
366366
signature.addFeatureSet(_contextFeatureSet);
367367
signature.addLanguageVersion(_packageLanguageVersion);
368368
signature.addString(_contentHash);
@@ -736,8 +736,8 @@ class FileSystemState {
736736
final SourceFactory _sourceFactory;
737737
final AnalysisOptions _analysisOptions;
738738
final DeclaredVariables _declaredVariables;
739-
final Uint32List _unlinkedSalt;
740-
final Uint32List _linkedSalt;
739+
final Uint32List _saltForUnlinked;
740+
final Uint32List _saltForElements;
741741

742742
final FeatureSetProvider featureSetProvider;
743743

@@ -795,8 +795,8 @@ class FileSystemState {
795795
this._sourceFactory,
796796
this._analysisOptions,
797797
this._declaredVariables,
798-
this._unlinkedSalt,
799-
this._linkedSalt,
798+
this._saltForUnlinked,
799+
this._saltForElements,
800800
this.featureSetProvider, {
801801
this.externalSummaries,
802802
}) {

pkg/analyzer/lib/src/dart/analysis/library_context.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ var timerLoad2 = Stopwatch();
3838
class LibraryContext {
3939
static const _maxLinkedDataInBytes = 64 * 1024 * 1024;
4040

41+
final LibraryContextTestView testView;
4142
final PerformanceLog logger;
4243
final ByteStore byteStore;
4344
final AnalysisSessionImpl analysisSession;
@@ -55,6 +56,7 @@ class LibraryContext {
5556
Set<LibraryCycle> loadedBundles = Set<LibraryCycle>.identity();
5657

5758
LibraryContext({
59+
@required this.testView,
5860
@required AnalysisSessionImpl session,
5961
@required PerformanceLog logger,
6062
@required ByteStore byteStore,
@@ -120,6 +122,10 @@ class LibraryContext {
120122
if (bytes == null) {
121123
librariesLinkedTimer.start();
122124

125+
testView.linkedCycles.add(
126+
cycle.libraries.map((e) => e.path).toSet(),
127+
);
128+
123129
timerInputLibraries.start();
124130
inputsTimer.start();
125131
var inputLibraries = <link2.LinkInputLibrary>[];
@@ -312,6 +318,10 @@ class LibraryContext {
312318
}
313319
}
314320

321+
class LibraryContextTestView {
322+
final List<Set<String>> linkedCycles = [];
323+
}
324+
315325
/// TODO(scheglov) replace in the internal patch
316326
class LibraryCycleLinkException extends CaughtExceptionWithFiles {
317327
LibraryCycleLinkException(

pkg/analyzer/lib/src/dart/analysis/library_graph.dart

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ import 'package:analyzer/src/summary/link.dart' as graph
1111

1212
/// Ensure that the [FileState.libraryCycle] for the [file] and anything it
1313
/// depends on is computed.
14-
void computeLibraryCycle(Uint32List linkedSalt, FileState file) {
15-
var libraryWalker = _LibraryWalker(linkedSalt);
14+
void computeLibraryCycle(Uint32List salt, FileState file) {
15+
var libraryWalker = _LibraryWalker(salt);
1616
libraryWalker.walk(libraryWalker.getNode(file));
1717
}
1818

@@ -88,10 +88,10 @@ class _LibraryNode extends graph.Node<_LibraryNode> {
8888
/// Helper that organizes dependencies of a library into topologically
8989
/// sorted [LibraryCycle]s.
9090
class _LibraryWalker extends graph.DependencyWalker<_LibraryNode> {
91-
final Uint32List _linkedSalt;
91+
final Uint32List _salt;
9292
final Map<FileState, _LibraryNode> nodesOfFiles = {};
9393

94-
_LibraryWalker(this._linkedSalt);
94+
_LibraryWalker(this._salt);
9595

9696
@override
9797
void evaluate(_LibraryNode v) {
@@ -103,7 +103,7 @@ class _LibraryWalker extends graph.DependencyWalker<_LibraryNode> {
103103
var cycle = LibraryCycle();
104104

105105
var signature = ApiSignature();
106-
signature.addUint32List(_linkedSalt);
106+
signature.addUint32List(_salt);
107107

108108
// Sort libraries to produce stable signatures.
109109
scc.sort((first, second) {

pkg/analyzer/lib/src/generated/engine.dart

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -216,9 +216,6 @@ class AnalysisErrorInfoImpl implements AnalysisErrorInfo {
216216
/// A set of analysis options used to control the behavior of an analysis
217217
/// context.
218218
abstract class AnalysisOptions {
219-
/// The length of the list returned by [signature].
220-
static const int signatureLength = 4;
221-
222219
/// Function that returns `true` if analysis is to parse and analyze function
223220
/// bodies for a given source.
224221
@deprecated
@@ -383,8 +380,8 @@ abstract class AnalysisOptions {
383380

384381
/// Determine whether two signatures returned by [signature] are equal.
385382
static bool signaturesEqual(Uint32List a, Uint32List b) {
386-
assert(a.length == signatureLength);
387-
assert(b.length == signatureLength);
383+
assert(a.length == AnalysisOptionsImpl.signatureLength);
384+
assert(b.length == AnalysisOptionsImpl.signatureLength);
388385
if (a.length != b.length) {
389386
return false;
390387
}
@@ -400,16 +397,16 @@ abstract class AnalysisOptions {
400397
/// A set of analysis options used to control the behavior of an analysis
401398
/// context.
402399
class AnalysisOptionsImpl implements AnalysisOptions {
400+
/// The length of the list returned by `signature` getters.
401+
static const int signatureLength = 4;
402+
403403
/// DEPRECATED: The maximum number of sources for which data should be kept in
404404
/// the cache.
405405
///
406406
/// This constant no longer has any effect.
407407
@deprecated
408408
static const int DEFAULT_CACHE_SIZE = 64;
409409

410-
/// The length of the list returned by [unlinkedSignature].
411-
static const int unlinkedSignatureLength = 4;
412-
413410
/// A predicate indicating whether analysis is to parse and analyze function
414411
/// bodies.
415412
@deprecated
@@ -422,6 +419,9 @@ class AnalysisOptionsImpl implements AnalysisOptions {
422419
/// The cached [signature].
423420
Uint32List _signature;
424421

422+
/// The cached [signatureForElements].
423+
Uint32List _signatureForElements;
424+
425425
@override
426426
VersionConstraint sdkVersionConstraint;
427427

@@ -770,6 +770,23 @@ class AnalysisOptionsImpl implements AnalysisOptions {
770770
return _signature;
771771
}
772772

773+
Uint32List get signatureForElements {
774+
if (_signatureForElements == null) {
775+
ApiSignature buffer = ApiSignature();
776+
777+
// Append features.
778+
buffer.addInt(ExperimentStatus.knownFeatures.length);
779+
for (var feature in ExperimentStatus.knownFeatures.values) {
780+
buffer.addBool(contextFeatures.isEnabled(feature));
781+
}
782+
783+
// Hash and convert to Uint32List.
784+
List<int> bytes = buffer.toByteList();
785+
_signatureForElements = Uint8List.fromList(bytes).buffer.asUint32List();
786+
}
787+
return _signatureForElements;
788+
}
789+
773790
@override
774791
bool get strongMode => true;
775792

0 commit comments

Comments
 (0)