Skip to content

Commit b678c7d

Browse files
committed
Improve performance of precompiled module invalidation in incremental builds
1 parent 06d4c79 commit b678c7d

File tree

1 file changed

+18
-40
lines changed

1 file changed

+18
-40
lines changed

Sources/SwiftDriver/IncrementalCompilation/FirstWaveComputer.swift

Lines changed: 18 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -149,12 +149,11 @@ extension IncrementalCompilationState.FirstWaveComputer {
149149
throws -> Set<ModuleDependencyId> {
150150
let mainModuleInfo = moduleDependencyGraph.mainModule
151151
var modulesRequiringRebuild: Set<ModuleDependencyId> = []
152-
var validatedModules: Set<ModuleDependencyId> = []
152+
var visitedModules: Set<ModuleDependencyId> = []
153153
// Scan from the main module's dependencies to avoid reporting
154154
// the main module itself in the results.
155155
for dependencyId in mainModuleInfo.directDependencies ?? [] {
156-
try outOfDateModuleScan(on: moduleDependencyGraph, from: dependencyId,
157-
pathSoFar: [], visitedValidated: &validatedModules,
156+
try outOfDateModuleScan(on: moduleDependencyGraph, from: dependencyId, visited: &visitedModules,
158157
modulesRequiringRebuild: &modulesRequiringRebuild)
159158
}
160159

@@ -167,54 +166,33 @@ extension IncrementalCompilationState.FirstWaveComputer {
167166
/// modules, along with the path from the root to this module.
168167
private func outOfDateModuleScan(on moduleDependencyGraph: InterModuleDependencyGraph,
169168
from moduleId: ModuleDependencyId,
170-
pathSoFar: [ModuleDependencyId],
171-
visitedValidated: inout Set<ModuleDependencyId>,
169+
visited: inout Set<ModuleDependencyId>,
172170
modulesRequiringRebuild: inout Set<ModuleDependencyId>) throws {
173171
let moduleInfo = try moduleDependencyGraph.moduleInfo(of: moduleId)
174-
let isMainModule = moduleId == .swift(moduleDependencyGraph.mainModuleName)
175-
176-
// Routine to invalidate the path from root to this node
177-
let invalidatePath = { (modulesRequiringRebuild: inout Set<ModuleDependencyId>) in
178-
if let reporter {
179-
for pathModuleId in pathSoFar {
180-
if !modulesRequiringRebuild.contains(pathModuleId) &&
181-
!isMainModule {
182-
reporter.reportExplicitDependencyWillBeReBuilt(pathModuleId.moduleNameForDiagnostic,
183-
reason: "Invalidated by downstream dependency")
184-
}
185-
}
186-
}
187-
modulesRequiringRebuild.formUnion(pathSoFar)
188-
}
189-
190-
// Routine to invalidate this node and the path that led to it
191-
let invalidateOutOfDate = { (modulesRequiringRebuild: inout Set<ModuleDependencyId>) in
192-
reporter?.reportExplicitDependencyWillBeReBuilt(moduleId.moduleNameForDiagnostic, reason: "Out-of-date")
193-
modulesRequiringRebuild.insert(moduleId)
194-
invalidatePath(&modulesRequiringRebuild)
195-
}
196-
197172
// Visit the module's dependencies
173+
var hasOutOfDateModuleDependency = false
198174
for dependencyId in moduleInfo.directDependencies ?? [] {
199-
if !visitedValidated.contains(dependencyId) {
200-
let newPath = pathSoFar + [moduleId]
201-
try outOfDateModuleScan(on: moduleDependencyGraph, from: dependencyId, pathSoFar: newPath,
202-
visitedValidated: &visitedValidated,
175+
// If we have not already visited this module, recurse.
176+
if !visited.contains(dependencyId) {
177+
try outOfDateModuleScan(on: moduleDependencyGraph, from: dependencyId,
178+
visited: &visited,
203179
modulesRequiringRebuild: &modulesRequiringRebuild)
204180
}
181+
// Even if we're not revisiting a dependency, we must check if it's already known to be out of date.
182+
hasOutOfDateModuleDependency = hasOutOfDateModuleDependency || modulesRequiringRebuild.contains(dependencyId)
205183
}
206184

207-
if modulesRequiringRebuild.contains(moduleId) {
208-
invalidatePath(&modulesRequiringRebuild)
185+
if hasOutOfDateModuleDependency {
186+
reporter?.reportExplicitDependencyWillBeReBuilt(moduleId.moduleNameForDiagnostic, reason: "Invalidated by downstream dependency")
187+
modulesRequiringRebuild.insert(moduleId)
209188
} else if try !IncrementalCompilationState.IncrementalDependencyAndInputSetup.verifyModuleDependencyUpToDate(moduleID: moduleId, moduleInfo: moduleInfo,
210189
fileSystem: fileSystem, reporter: reporter) {
211-
invalidateOutOfDate(&modulesRequiringRebuild)
212-
} else {
213-
// Only if this module is known to be up-to-date with respect to its inputs
214-
// and dependencies do we mark it as visited. We may need to re-visit
215-
// out-of-date modules in order to collect all possible paths to them.
216-
visitedValidated.insert(moduleId)
190+
reporter?.reportExplicitDependencyWillBeReBuilt(moduleId.moduleNameForDiagnostic, reason: "Out-of-date")
191+
modulesRequiringRebuild.insert(moduleId)
217192
}
193+
194+
// Now that we've determined if this module must be rebuilt, mark it as visited.
195+
visited.insert(moduleId)
218196
}
219197

220198
/// In an explicit module build, filter out dependency module pre-compilation tasks

0 commit comments

Comments
 (0)