Skip to content

Commit a3c58f9

Browse files
committed
Add caching of unsuccessful Swift dependency lookups
Use it to avoid unnecessary re-queries of Swift dependencies during a given scanning action.
1 parent 512ef2e commit a3c58f9

File tree

5 files changed

+36
-7
lines changed

5 files changed

+36
-7
lines changed

include/swift/AST/ModuleDependencies.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,6 +1073,9 @@ class ModuleDependenciesCache {
10731073
private:
10741074
/// Discovered dependencies
10751075
ModuleDependenciesKindMap ModuleDependenciesMap;
1076+
/// A set of module identifiers for which a scanning action failed
1077+
/// to discover a Swift module dependency
1078+
llvm::StringSet<> negativeSwiftDependencyCache;
10761079
/// Set containing all of the Clang modules that have already been seen.
10771080
llvm::DenseSet<clang::tooling::dependencies::ModuleID> alreadySeenClangModules;
10781081
/// Name of the module under scan
@@ -1111,6 +1114,10 @@ class ModuleDependenciesCache {
11111114
bool hasDependency(StringRef moduleName) const;
11121115
/// Whether we have cached dependency information for the given Swift module.
11131116
bool hasSwiftDependency(StringRef moduleName) const;
1117+
/// Whether we have previously failed a lookup of a Swift dependency for the
1118+
/// given identifier.
1119+
bool hasNegativeSwiftDependency(StringRef moduleName) const;
1120+
11141121
/// Report the number of recorded Clang dependencies
11151122
int numberOfClangDependencies() const;
11161123
/// Report the number of recorded Swift dependencies
@@ -1232,6 +1239,8 @@ class ModuleDependenciesCache {
12321239
void
12331240
addVisibleClangModules(ModuleDependencyID moduleID,
12341241
const std::vector<std::string> &moduleNames);
1242+
/// Add an identifier to the set of failed Swift module queries
1243+
void recordFailedSwiftDependencyLookup(StringRef moduleIdentifier);
12351244

12361245
StringRef getMainModuleName() const { return mainScanModuleName; }
12371246

lib/AST/ModuleDependencies.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -760,14 +760,17 @@ bool ModuleDependenciesCache::hasSwiftDependency(StringRef moduleName) const {
760760
return findSwiftDependency(moduleName).has_value();
761761
}
762762

763+
bool ModuleDependenciesCache::hasNegativeSwiftDependency(StringRef moduleName) const {
764+
return negativeSwiftDependencyCache.contains(moduleName);
765+
}
766+
763767
int ModuleDependenciesCache::numberOfClangDependencies() const {
764768
return ModuleDependenciesMap.at(ModuleDependencyKind::Clang).size();
765769
}
766770
int ModuleDependenciesCache::numberOfSwiftDependencies() const {
767771
return ModuleDependenciesMap.at(ModuleDependencyKind::SwiftInterface).size() +
768772
ModuleDependenciesMap.at(ModuleDependencyKind::SwiftBinary).size();
769773
}
770-
771774
void ModuleDependenciesCache::recordDependency(
772775
StringRef moduleName, ModuleDependencyInfo dependency) {
773776
auto dependenciesKind = dependency.getKind();
@@ -946,6 +949,11 @@ void ModuleDependenciesCache::addVisibleClangModules(
946949
updateDependency(moduleID, updatedDependencyInfo);
947950
}
948951

952+
void ModuleDependenciesCache::recordFailedSwiftDependencyLookup(
953+
StringRef moduleIdentifier) {
954+
negativeSwiftDependencyCache.insert(moduleIdentifier);
955+
}
956+
949957
llvm::StringSet<> &ModuleDependenciesCache::getVisibleClangModules(
950958
ModuleDependencyID moduleID) const {
951959
ASSERT(moduleID.Kind == ModuleDependencyKind::SwiftSource ||

lib/DependencyScan/ModuleDependencyScanner.cpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "swift/Basic/Defer.h"
2727
#include "swift/Basic/FileTypes.h"
2828
#include "swift/Basic/PrettyStackTrace.h"
29+
#include "swift/Basic/Statistic.h"
2930
#include "swift/ClangImporter/ClangImporter.h"
3031
#include "swift/Frontend/CompileJobCacheKey.h"
3132
#include "swift/Frontend/ModuleInterfaceLoader.h"
@@ -1389,6 +1390,13 @@ void ModuleDependencyScanner::resolveSwiftImportsForModule(
13891390
// Avoid querying the underlying Clang module here
13901391
if (moduleID.ModuleName == dependsOn.importIdentifier)
13911392
continue;
1393+
// Avoid querying Swift module dependencies previously discovered
1394+
if (DependencyCache.hasSwiftDependency(dependsOn.importIdentifier))
1395+
continue;
1396+
// Avoid querying Swift module dependencies which have already produced
1397+
// in a negative (not found) result
1398+
if (DependencyCache.hasNegativeSwiftDependency(dependsOn.importIdentifier))
1399+
continue;
13921400
ScanningThreadPool.async(
13931401
scanForSwiftModuleDependency,
13941402
getModuleImportIdentifier(dependsOn.importIdentifier),
@@ -1428,10 +1436,13 @@ void ModuleDependencyScanner::resolveSwiftImportsForModule(
14281436
moduleImport.importIdentifier))
14291437
importedSwiftDependencies.insert(
14301438
{moduleImport.importIdentifier, cachedInfo.value()->getKind()});
1431-
else
1439+
else {
14321440
ScanDiagnosticReporter.diagnoseFailureOnOnlyIncompatibleCandidates(
14331441
moduleImport, lookupResult.incompatibleCandidates,
14341442
DependencyCache, std::nullopt);
1443+
DependencyCache
1444+
.recordFailedSwiftDependencyLookup(moduleImport.importIdentifier);
1445+
}
14351446
};
14361447

14371448
for (const auto &importInfo : moduleDependencyInfo.getModuleImports())
@@ -1575,10 +1586,9 @@ void ModuleDependencyScanner::resolveSwiftOverlayDependenciesForModule(
15751586
auto moduleName = moduleIdentifier.str();
15761587
{
15771588
std::lock_guard<std::mutex> guard(lookupResultLock);
1578-
if (DependencyCache.hasDependency(moduleName,
1579-
ModuleDependencyKind::SwiftInterface) ||
1580-
DependencyCache.hasDependency(moduleName,
1581-
ModuleDependencyKind::SwiftBinary))
1589+
if (DependencyCache.hasDependency(moduleName, ModuleDependencyKind::SwiftInterface) ||
1590+
DependencyCache.hasDependency(moduleName, ModuleDependencyKind::SwiftBinary) ||
1591+
DependencyCache.hasNegativeSwiftDependency(moduleName))
15821592
return;
15831593
}
15841594

test/ScanDependencies/basic_query_metrics.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
// RUN: cat %t/remarks.txt | %FileCheck %s
88

99
// Ensure that despite being a common dependency to multiple Swift modules, only 1 query is performed to find 'C'
10-
// CHECK: remark: Number of Swift module queries: '6'
10+
// CHECK: remark: Number of Swift module queries: '3'
1111
// CHECK: remark: Number of named Clang module queries: '1'
1212
// CHEKC: remark: Number of recorded Clang module dependencies queried by-name from a Swift client: '1'
1313
// CHECK: remark: Number of recorded Swift module dependencies: '2'

test/ScanDependencies/module_deps_cache_reuse.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ import SubE
2828
// CHECK-REMARK-SAVE: remark: Incremental module scan: Serializing module scanning dependency cache to:
2929

3030
// CHECK-REMARK-LOAD: remark: Incremental module scan: Re-using serialized module scanning dependency cache from:
31+
// 'SwiftShims', 'C' and 'B' are Clang modules which are directly imorted from Swift code in this test, without a corresponding Swift overlay module. Because we do not serialize negative Swift dependency lookup results, resolving a dependency on these modules involves a query for whether a Swift module under this name can be found. This query fails and the subsequent query for this identifier as a Clang dependency is then able to re-use the loaded serialized cache.
32+
// CHECK-REMARK-LOAD: remark: Number of Swift module queries: '3'
3133
// FIXME: Today, we do not serialize dependencies of the main source module which results in a lookup for 'C' even though
3234
// it is fully redundant.
3335
// CHECK-REMARK-LOAD: remark: Number of named Clang module queries: '1'

0 commit comments

Comments
 (0)