Skip to content

Improve Deserialization Performance #734

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 3 commits into from
Jun 30, 2021
Merged
Show file tree
Hide file tree
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
35 changes: 6 additions & 29 deletions Sources/SwiftDriver/IncrementalCompilation/DependencyKey.swift
Original file line number Diff line number Diff line change
Expand Up @@ -308,16 +308,12 @@ public struct DependencyKey: CustomStringConvertible {
/*@_spi(Testing)*/ public let aspect: DeclAspect
/*@_spi(Testing)*/ public let designator: Designator

private let cachedHash: Int


/*@_spi(Testing)*/ public init(
aspect: DeclAspect,
designator: Designator)
{
self.aspect = aspect
self.designator = designator
self.cachedHash = Self.computeHash(aspect, designator)
}

/*@_spi(Testing)*/ public var correspondingImplementation: Self? {
Expand All @@ -338,35 +334,16 @@ public struct DependencyKey: CustomStringConvertible {
}
}

extension DependencyKey: Equatable, Hashable {

private static func computeHash(_ aspect: DeclAspect, _ designator: Designator) -> Int {
var h = Hasher()
h.combine(aspect)
h.combine(designator)
return h.finalize()
}

public func hash(into hasher: inout Hasher) {
hasher.combine(cachedHash)
}

public static func ==(lhs: Self, rhs: Self) -> Bool {
lhs.aspect == rhs.aspect && lhs.designator == rhs.designator
}
}

// MARK: - Comparing
/// Needed to sort nodes to make tracing deterministic to test against emitted diagnostics
extension DependencyKey: Comparable {
extension DependencyKey: Equatable, Hashable, Comparable {
public static func < (lhs: Self, rhs: Self) -> Bool {
lhs.aspect != rhs.aspect ? lhs.aspect < rhs.aspect :
lhs.designator < rhs.designator
guard lhs.aspect == rhs.aspect else {
return lhs.aspect < rhs.aspect
}
return lhs.designator < rhs.designator
}
}

extension DependencyKey.Designator: Comparable {
}
extension DependencyKey.Designator: Comparable {}

// MARK: - InvalidationReason
extension ExternalDependency {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -583,21 +583,19 @@ extension ModuleDependencyGraph {
throw ReadError.unexpectedMetadataRecord
}
guard record.fields.count == 2,
case .blob(let compilerVersionBlob) = record.payload,
let compilerVersionString = String(data: compilerVersionBlob, encoding: .utf8)
case .blob(let compilerVersionBlob) = record.payload
else { throw ReadError.malformedMetadataRecord }

self.majorVersion = record.fields[0]
self.minorVersion = record.fields[1]
self.compilerVersionString = compilerVersionString
self.compilerVersionString = String(decoding: compilerVersionBlob, as: UTF8.self)
case .moduleDepGraphNode:
let kindCode = record.fields[0]
guard record.fields.count == 7,
let declAspect = DependencyKey.DeclAspect(record.fields[1]),
record.fields[2] < identifiers.count,
record.fields[3] < identifiers.count,
case .blob(let fingerprintBlob) = record.payload,
let fingerprintStr = String(data: fingerprintBlob, encoding: .utf8)
case .blob(let fingerprintBlob) = record.payload
else {
throw ReadError.malformedModuleDepGraphNodeRecord
}
Expand All @@ -609,7 +607,7 @@ extension ModuleDependencyGraph {
let hasDepSource = Int(record.fields[4]) != 0
let depSourceStr = hasDepSource ? identifiers[Int(record.fields[5])] : nil
let hasFingerprint = Int(record.fields[6]) != 0
let fingerprint = hasFingerprint ? fingerprintStr : nil
let fingerprint = hasFingerprint ? String(decoding: fingerprintBlob, as: UTF8.self) : nil
guard let dependencySource = try depSourceStr
.map({ try VirtualPath.intern(path: $0) })
.map(DependencySource.init)
Expand Down Expand Up @@ -641,24 +639,22 @@ extension ModuleDependencyGraph {
case .externalDepNode:
guard record.fields.count == 2,
record.fields[0] < identifiers.count,
case .blob(let fingerprintBlob) = record.payload,
let fingerprintStr = String(data: fingerprintBlob, encoding: .utf8)
case .blob(let fingerprintBlob) = record.payload
else {
throw ReadError.malformedExternalDepNodeRecord
}
let path = identifiers[Int(record.fields[0])]
let hasFingerprint = Int(record.fields[1]) != 0
let fingerprint = hasFingerprint ? fingerprintStr : nil
let fingerprint = hasFingerprint ? String(decoding: fingerprintBlob, as: UTF8.self) : nil
self.graph.fingerprintedExternalDependencies.insert(
FingerprintedExternalDependency(ExternalDependency(fileName: path), fingerprint))
case .identifierNode:
guard record.fields.count == 0,
case .blob(let identifierBlob) = record.payload,
let identifier = String(data: identifierBlob, encoding: .utf8)
case .blob(let identifierBlob) = record.payload
else {
throw ReadError.malformedIdentifierRecord
}
identifiers.append(identifier)
identifiers.append(String(decoding: identifierBlob, as: UTF8.self))
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,8 +213,8 @@ extension SourceFileDependencyGraph {
defsIDependUpon: defsNodeDependUpon,
isProvides: isProvides)
self.key = nil
defsNodeDependUpon = []
nodes.append(node)
self.defsNodeDependUpon.removeAll(keepingCapacity: true)
self.nodes.append(node)
}
mutating func visit(record: BitcodeElement.Record) throws {
guard let kind = RecordKind(rawValue: record.id) else { throw ReadError.unknownRecord }
Expand All @@ -225,13 +225,12 @@ extension SourceFileDependencyGraph {
throw ReadError.unexpectedMetadataRecord
}
guard record.fields.count == 2,
case .blob(let compilerVersionBlob) = record.payload,
let compilerVersionString = String(data: compilerVersionBlob, encoding: .utf8)
case .blob(let compilerVersionBlob) = record.payload
else { throw ReadError.malformedMetadataRecord }

self.majorVersion = record.fields[0]
self.minorVersion = record.fields[1]
self.compilerVersionString = compilerVersionString
self.compilerVersionString = String(decoding: compilerVersionBlob, as: UTF8.self)
case .sourceFileDepGraphNode:
try finalizeNode()
let kindCode = record.fields[0]
Expand All @@ -249,28 +248,28 @@ extension SourceFileDependencyGraph {
self.key = DependencyKey(aspect: declAspect, designator: designator)
self.fingerprint = nil
self.nodeSequenceNumber = nextSequenceNumber
self.defsNodeDependUpon = []
self.defsNodeDependUpon.removeAll(keepingCapacity: true)

nextSequenceNumber += 1
case .fingerprintNode:
guard key != nil,
record.fields.count == 0,
case .blob(let fingerprintBlob) = record.payload,
let fingerprint = String(data: fingerprintBlob, encoding: .utf8) else {
case .blob(let fingerprintBlob) = record.payload
else {
throw ReadError.malformedFingerprintRecord
}
self.fingerprint = fingerprint
self.fingerprint = String(decoding: fingerprintBlob, as: UTF8.self)
case .dependsOnDefinitionNode:
guard key != nil,
record.fields.count == 1 else { throw ReadError.malformedDependsOnDefinitionRecord }
self.defsNodeDependUpon.append(Int(record.fields[0]))
case .identifierNode:
guard record.fields.count == 0,
case .blob(let identifierBlob) = record.payload,
let identifier = String(data: identifierBlob, encoding: .utf8) else {
case .blob(let identifierBlob) = record.payload
else {
throw ReadError.malformedIdentifierRecord
}
identifiers.append(identifier)
identifiers.append(String(decoding: identifierBlob, as: UTF8.self))
}
}
}
Expand Down