Skip to content

[Incremental] Try a cache for external dependency mod times #538

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 13, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ import SwiftOptions

@_spi(Testing) public var phase: Phase

/// Minimize the number of file system modification-time queries.
private var externalDependencyModTimeCache = [ExternalDependency: Bool]()

public init(_ info: IncrementalCompilationState.InitialStateComputer,
_ phase: Phase
) {
Expand Down Expand Up @@ -287,14 +290,10 @@ extension ModuleDependencyGraph {

let isNewToTheGraph = fingerprintedExternalDependencies.insert(fed).inserted

var lazyModTimer = LazyModTimer(
externalDependency: fed.externalDependency,
info: info)

// If the graph already includes prior externals, then any new externals are changes
// Short-circuit conjunction may avoid the modTime query
let shouldTryToProcess = info.isCrossModuleIncrementalBuildEnabled &&
(isNewToTheGraph || lazyModTimer.hasExternalFileChanged)
(isNewToTheGraph || hasFileChanged(of: fed.externalDependency))

// Do this no matter what in order to integrate any incremental external dependencies.
let invalidatedNodesFromIncrementalExternal = shouldTryToProcess
Expand All @@ -309,7 +308,7 @@ extension ModuleDependencyGraph {
/// When building a graph from scratch, an unchanged but new-to-the-graph external dependendcy should be ignored.
/// Otherwise, it represents an added Import
let callerWantsTheseChanges = (phase.isUpdating && isNewToTheGraph) ||
lazyModTimer.hasExternalFileChanged
hasFileChanged(of: fed.externalDependency)

guard callerWantsTheseChanges else {
return DirectlyInvalidatedNodeSet()
Expand All @@ -319,13 +318,16 @@ extension ModuleDependencyGraph {
// return anything that uses that dependency.
return invalidatedNodesFromIncrementalExternal ?? collectUntracedNodesUsing(fed)
}

private struct LazyModTimer {
let externalDependency: ExternalDependency
let info: IncrementalCompilationState.InitialStateComputer

lazy var hasExternalFileChanged = (externalDependency.modTime(info.fileSystem) ?? .distantFuture)
private func hasFileChanged(of externalDependency: ExternalDependency
) -> Bool {
if let hasChanged = externalDependencyModTimeCache[externalDependency] {
return hasChanged
}
let hasChanged = (externalDependency.modTime(info.fileSystem) ?? .distantFuture)
>= info.buildTime
externalDependencyModTimeCache[externalDependency] = hasChanged
return hasChanged
}

/// Try to read and integrate an external dependency.
Expand Down