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


    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)

    // Do this no matter what in order to integrate any incremental external dependencies.
    let invalidatedNodesFromIncrementalExternal = shouldTryToProcess

  let dotFileWriter: DependencyGraphDotFileWriter?

  @_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
