Skip to content

Commit 8f1d770

Browse files
author
David Ungar
authored
Merge pull request #502 from davidungar/isUntraced
Optimize performance by replacing a set of nodes with a bit in each node.
2 parents 2df58da + d08f883 commit 8f1d770

File tree

5 files changed

+24
-23
lines changed

5 files changed

+24
-23
lines changed

Sources/SwiftDriver/IncrementalCompilation/ModuleDependencyGraph.swift

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,6 @@ import SwiftOptions
2323

2424
@_spi(Testing) public var nodeFinder = NodeFinder()
2525

26-
/// When integrating a change, want to find untraced nodes so we can kick off jobs that have not been
27-
/// kicked off yet
28-
private var tracedNodes = Set<Node>()
29-
3026
/// Maps input files (e.g. .swift) to and from the DependencySource object
3127
@_spi(Testing) public private(set) var inputDependencySourceMap = BidirectionalMap<TypedVirtualPath, DependencySource>()
3228

@@ -207,7 +203,7 @@ extension ModuleDependencyGraph {
207203
dependencySource: nil)
208204
return nodeFinder
209205
.uses(of: node)
210-
.filter({ use in isUntraced(use) })
206+
.filter({ use in use.isUntraced })
211207
}
212208

213209
/// Find all the inputs known to need recompilation as a consequence of reading a swiftdeps or swiftmodule
@@ -345,19 +341,12 @@ extension OutputFileMap {
345341
// MARK: - tracking traced nodes
346342
extension ModuleDependencyGraph {
347343

348-
func isUntraced(_ n: Node) -> Bool {
349-
!isTraced(n)
350-
}
351-
@_spi(Testing) public func isTraced(_ n: Node) -> Bool {
352-
tracedNodes.contains(n)
353-
}
354-
func amTracing(_ n: Node) {
355-
tracedNodes.insert(n)
356-
}
357-
func ensureGraphWillRetraceDependents<Nodes: Sequence>(of nodes: Nodes)
344+
func ensureGraphWillRetrace<Nodes: Sequence>(_ nodes: Nodes)
358345
where Nodes.Element == Node
359346
{
360-
nodes.forEach { tracedNodes.remove($0) }
347+
for node in nodes {
348+
node.setUntraced()
349+
}
361350
}
362351
}
363352

@@ -1074,7 +1063,6 @@ extension Diagnostic.Message {
10741063
extension ModuleDependencyGraph {
10751064
func matches(_ other: ModuleDependencyGraph) -> Bool {
10761065
guard nodeFinder.matches(other.nodeFinder),
1077-
tracedNodes.matches(other.tracedNodes),
10781066
inputDependencySourceMap.matches(other.inputDependencySourceMap),
10791067
fingerprintedExternalDependencies.matches(other.fingerprintedExternalDependencies)
10801068
else {

Sources/SwiftDriver/IncrementalCompilation/ModuleDependencyGraphParts/Integrator.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ extension ModuleDependencyGraph.Integrator {
9191
private mutating func integrate() {
9292
integrateEachSourceNode()
9393
handleDisappearedNodes()
94-
destination.ensureGraphWillRetraceDependents(of: results.allInvalidatedNodes)
94+
destination.ensureGraphWillRetrace(results.allInvalidatedNodes)
9595
}
9696
private mutating func integrateEachSourceNode() {
9797
sourceGraph.forEachNode { integrate(oneNode: $0) }

Sources/SwiftDriver/IncrementalCompilation/ModuleDependencyGraphParts/Node.swift

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ extension ModuleDependencyGraph {
2424
///
2525
/// Use a class, not a struct because otherwise it would be duplicated for each thing it uses
2626

27-
/*@_spi(Testing)*/
2827
public final class Node {
2928

3029
/*@_spi(Testing)*/ public typealias Graph = ModuleDependencyGraph
@@ -44,6 +43,12 @@ extension ModuleDependencyGraph {
4443
let dependencySource: DependencySource?
4544
var isExpat: Bool { dependencySource == nil }
4645

46+
/// When integrating a change, the driver finds untraced nodes so it can kick off jobs that have not been
47+
/// kicked off yet. (Within any one driver invocation, compiling a source file is idempotent.)
48+
/// When reading a serialized, prior graph, *don't* recover this state, since it will be a new driver
49+
/// invocation that has not kicked off any compiles yet.
50+
@_spi(Testing) public private(set) var isTraced: Bool = false
51+
4752
/// This dependencySource is the file where the swiftDeps, etc. was read, not necessarily anything in the
4853
/// SourceFileDependencyGraph or the DependencyKeys
4954
init(key: DependencyKey, fingerprint: String?,
@@ -53,6 +58,14 @@ extension ModuleDependencyGraph {
5358
}
5459
}
5560
}
61+
62+
// MARK: - trace status
63+
extension ModuleDependencyGraph.Node {
64+
var isUntraced: Bool { !isTraced }
65+
func setTraced() { isTraced = true }
66+
func setUntraced() { isTraced = false }
67+
}
68+
5669
// MARK: - comparing, hashing
5770
extension ModuleDependencyGraph.Node: Equatable, Hashable {
5871
public static func == (lhs: Graph.Node, rhs: Graph.Node) -> Bool {

Sources/SwiftDriver/IncrementalCompilation/ModuleDependencyGraphParts/Tracer.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ extension ModuleDependencyGraph.Tracer {
7272
private mutating func collectNextPreviouslyUntracedDependent(
7373
of definition: ModuleDependencyGraph.Node
7474
) {
75-
guard graph.isUntraced(definition) else { return }
76-
graph.amTracing(definition)
75+
guard definition.isUntraced else { return }
76+
definition.setTraced()
7777

7878
tracedUses.append(definition)
7979

Tests/SwiftDriverTests/Helpers/MockingIncrementalCompilation.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ extension ModuleDependencyGraph {
2020
let dependencySource = DependencySource(mock: i)
2121
// optimization
2222
if let fileNode = nodeFinder.findFileInterfaceNode(forMock: dependencySource),
23-
isTraced(fileNode) {
23+
fileNode.isTraced {
2424
return true
2525
}
2626
if let nodes = nodeFinder.findNodes(for: dependencySource)?.values,
27-
nodes.contains(where: isTraced) {
27+
nodes.contains(where: {$0.isTraced}) {
2828
return true
2929
}
3030
return false

0 commit comments

Comments
 (0)