Skip to content

Commit fba2886

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 fe53e14 commit fba2886

File tree

6 files changed

+38
-10
lines changed

6 files changed

+38
-10
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
@@ -772,14 +772,17 @@ bool ModuleDependenciesCache::hasSwiftDependency(StringRef moduleName) const {
772772
return findSwiftDependency(moduleName).has_value();
773773
}
774774

775+
bool ModuleDependenciesCache::hasNegativeSwiftDependency(StringRef moduleName) const {
776+
return negativeSwiftDependencyCache.contains(moduleName);
777+
}
778+
775779
int ModuleDependenciesCache::numberOfClangDependencies() const {
776780
return ModuleDependenciesMap.at(ModuleDependencyKind::Clang).size();
777781
}
778782
int ModuleDependenciesCache::numberOfSwiftDependencies() const {
779783
return ModuleDependenciesMap.at(ModuleDependencyKind::SwiftInterface).size() +
780784
ModuleDependenciesMap.at(ModuleDependencyKind::SwiftBinary).size();
781785
}
782-
783786
void ModuleDependenciesCache::recordDependency(
784787
StringRef moduleName, ModuleDependencyInfo dependency) {
785788
auto dependenciesKind = dependency.getKind();
@@ -958,6 +961,11 @@ void ModuleDependenciesCache::addVisibleClangModules(
958961
updateDependency(moduleID, updatedDependencyInfo);
959962
}
960963

964+
void ModuleDependenciesCache::recordFailedSwiftDependencyLookup(
965+
StringRef moduleIdentifier) {
966+
negativeSwiftDependencyCache.insert(moduleIdentifier);
967+
}
968+
961969
llvm::StringSet<> &ModuleDependenciesCache::getVisibleClangModules(
962970
ModuleDependencyID moduleID) const {
963971
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"
@@ -1347,6 +1348,13 @@ void ModuleDependencyScanner::resolveSwiftImportsForModule(
13471348
// Avoid querying the underlying Clang module here
13481349
if (moduleID.ModuleName == dependsOn.importIdentifier)
13491350
continue;
1351+
// Avoid querying Swift module dependencies previously discovered
1352+
if (DependencyCache.hasSwiftDependency(dependsOn.importIdentifier))
1353+
continue;
1354+
// Avoid querying Swift module dependencies which have already produced
1355+
// in a negative (not found) result
1356+
if (DependencyCache.hasNegativeSwiftDependency(dependsOn.importIdentifier))
1357+
continue;
13501358
ScanningThreadPool.async(
13511359
scanForSwiftModuleDependency,
13521360
getModuleImportIdentifier(dependsOn.importIdentifier),
@@ -1386,10 +1394,13 @@ void ModuleDependencyScanner::resolveSwiftImportsForModule(
13861394
moduleImport.importIdentifier))
13871395
importedSwiftDependencies.insert(
13881396
{moduleImport.importIdentifier, cachedInfo.value()->getKind()});
1389-
else
1397+
else {
13901398
ScanDiagnosticReporter.diagnoseFailureOnOnlyIncompatibleCandidates(
13911399
moduleImport, lookupResult.incompatibleCandidates,
13921400
DependencyCache, std::nullopt);
1401+
DependencyCache
1402+
.recordFailedSwiftDependencyLookup(moduleImport.importIdentifier);
1403+
}
13931404
};
13941405

13951406
for (const auto &importInfo : moduleDependencyInfo.getModuleImports())
@@ -1533,10 +1544,9 @@ void ModuleDependencyScanner::resolveSwiftOverlayDependenciesForModule(
15331544
auto moduleName = moduleIdentifier.str();
15341545
{
15351546
std::lock_guard<std::mutex> guard(lookupResultLock);
1536-
if (DependencyCache.hasDependency(moduleName,
1537-
ModuleDependencyKind::SwiftInterface) ||
1538-
DependencyCache.hasDependency(moduleName,
1539-
ModuleDependencyKind::SwiftBinary))
1547+
if (DependencyCache.hasDependency(moduleName, ModuleDependencyKind::SwiftInterface) ||
1548+
DependencyCache.hasDependency(moduleName, ModuleDependencyKind::SwiftBinary) ||
1549+
DependencyCache.hasNegativeSwiftDependency(moduleName))
15401550
return;
15411551
}
15421552

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/diagnose_dependency_cycle_source_target.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55

66
// RUN: %FileCheck %s < %t/out.txt
77

8-
// CHECK: module dependency cycle: 'CycleOverlay (Source Target) -> CycleSwiftMiddle.swiftinterface -> CycleOverlay.swiftinterface'
8+
// CHECK: error: module dependency cycle: 'CycleOverlay (Source Target) -> CycleSwiftMiddle.swiftinterface -> CycleOverlay (Source Target)'
99
// CHECK: Swift Overlay dependency of 'CycleSwiftMiddle' on 'CycleOverlay' via Clang module dependency: 'CycleSwiftMiddle.swiftinterface -> CycleClangMiddle.pcm -> CycleOverlay.pcm'
10+
// CHECK: source target 'CycleOverlay' shadowing a Swift module with the same name
1011

1112
import CycleSwiftMiddle
1213

test/ScanDependencies/module_deps_cache_reuse.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import E
2121
import G
2222
import SubE
2323

24-
// CHECK-REMARK-SAVE: remark: Number of Swift module queries: '21'
24+
// CHECK-REMARK-SAVE: remark: Number of Swift module queries: '12'
2525
// CHECK-REMARK-SAVE: remark: Number of named Clang module queries: '6'
2626
// CHECK-REMARK-SAVE: remark: Number of recorded Clang module dependencies queried by-name from a Swift client: '6'
2727
// CHECK-REMARK-SAVE: remark: Number of recorded Swift module dependencies: '8'
@@ -31,7 +31,7 @@ import SubE
3131
// CHECK-REMARK-LOAD: remark: Incremental module scan: Re-using serialized module scanning dependency cache from:
3232
// '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.
3333

34-
// CHECK-REMARK-LOAD: remark: Number of Swift module queries: '7'
34+
// CHECK-REMARK-LOAD: remark: Number of Swift module queries: '3'
3535
// FIXME: Today, we do not serialize dependencies of the main source module which results in a lookup for 'C' even though
3636
// it is fully redundant.
3737
// CHECK-REMARK-LOAD: remark: Number of named Clang module queries: '1'

0 commit comments

Comments
 (0)