Skip to content

Commit a14a98f

Browse files
committed
[BuildOperation] Include in the build log a summary about the cache hit/miss metrics
This is only when compilation caching is in effect. rdar://147356859
1 parent 8289802 commit a14a98f

File tree

4 files changed

+42
-4
lines changed

4 files changed

+42
-4
lines changed

Sources/SWBBuildSystem/BuildOperation.swift

+25-2
Original file line numberDiff line numberDiff line change
@@ -665,8 +665,31 @@ package final class BuildOperation: BuildSystemOperation {
665665
}
666666
}
667667

668+
do {
669+
let swiftCacheHits = self.delegate.aggregatedCounters[.swiftCacheHits, default: 0]
670+
let swiftCacheMisses = self.delegate.aggregatedCounters[.swiftCacheMisses, default: 0]
671+
let clangCacheHits = self.delegate.aggregatedCounters[.clangCacheHits, default: 0]
672+
let clangCacheMisses = self.delegate.aggregatedCounters[.clangCacheMisses, default: 0]
673+
if swiftCacheHits + swiftCacheMisses > 0 || clangCacheHits + clangCacheMisses > 0 {
674+
adaptor.withActivity(ruleInfo: "CompilationCacheMetrics", executionDescription: "Report compilation cache metrics", signature: "compilation_cache_metrics", target: nil, parentActivity: nil) { activity in
675+
func getSummary(hits: Int, misses: Int) -> String {
676+
let hitPercent = Int((Double(hits) / Double(hits + misses) * 100).rounded())
677+
return "\(hits) hit\(hits == 1 ? "" : "s") (\(hitPercent)%), \(misses) miss\(misses == 1 ? "" : "es")"
678+
}
679+
if swiftCacheHits + swiftCacheMisses > 0 {
680+
delegate.emit(data: ByteString(encodingAsUTF8: "Swift compiler: \(getSummary(hits: swiftCacheHits, misses: swiftCacheMisses))").bytes, for: activity, signature: "compilation_cache_metrics")
681+
}
682+
if clangCacheHits + clangCacheMisses > 0 {
683+
delegate.emit(data: ByteString(encodingAsUTF8: "Clang compiler: \(getSummary(hits: clangCacheHits, misses: clangCacheMisses))").bytes, for: activity, signature: "compilation_cache_metrics")
684+
}
685+
return .succeeded
686+
}
687+
688+
}
689+
}
690+
668691
if SWBFeatureFlag.enableCacheMetricsLogs.value {
669-
adaptor.withActivity(ruleInfo: "CacheMetrics", executionDescription: "Report cache metrics", signature: "cache_metrics", target: nil, parentActivity: nil) { activity in
692+
adaptor.withActivity(ruleInfo: "RawCacheMetrics", executionDescription: "Report raw cache metrics", signature: "raw_cache_metrics", target: nil, parentActivity: nil) { activity in
670693
struct AllCounters: Encodable {
671694
var global: [String: Double] = [:]
672695
var tasks: [String: [String: Double]] = [:]
@@ -682,7 +705,7 @@ package final class BuildOperation: BuildSystemOperation {
682705
}
683706
serializedCounters.tasks[taskId] = serialTaskCounters
684707
}
685-
delegate.emit(data: ByteString(encodingAsUTF8: "\(serializedCounters)").bytes, for: activity, signature: "cache_metrics")
708+
delegate.emit(data: ByteString(encodingAsUTF8: "\(serializedCounters)").bytes, for: activity, signature: "raw_cache_metrics")
686709
return .succeeded
687710
}
688711
}

Sources/SWBTestSupport/BuildOperationTester.swift

+10-1
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,9 @@ package final class BuildOperationTester {
136136
/// A generic activity produced a diagnostic.
137137
case activityHadDiagnostic(ActivityID, Diagnostic)
138138

139+
/// A generic activity produced output.
140+
case activityEmittedData(ruleInfo: String, [UInt8])
141+
139142
/// A generic activity ended.
140143
case activityEnded(ruleInfo: String, status: BuildOperationTaskEnded.Status)
141144

@@ -179,6 +182,8 @@ package final class BuildOperationTester {
179182
return "activityStarted(\(ruleInfo))"
180183
case .activityHadDiagnostic(let activityID, let diagnostic):
181184
return "activityHadDiagnostic(\(activityID),\(diagnostic))"
185+
case .activityEmittedData(ruleInfo: let ruleInfo, let bytes):
186+
return "activityEmittedData(\(ruleInfo), bytes: \(ByteString(bytes).asString)"
182187
case .activityEnded(ruleInfo: let ruleInfo):
183188
return "activityEnded(\(ruleInfo))"
184189
case .emittedBuildBacktraceFrame(identifier: let id, previousFrameIdentifier: let previousID, category: let category, description: let description):
@@ -2156,7 +2161,11 @@ private final class BuildOperationTesterDelegate: BuildOperationDelegate {
21562161

21572162
func emit(data: [UInt8], for activity: ActivityID, signature: ByteString) {
21582163
queue.async {
2159-
// FIXME.
2164+
guard let ruleInfo = self.activitiesByActivityID[activity.rawValue] else {
2165+
assertionFailure("Received emit message for activity id '\(activity.rawValue)' but it was not started, or has already ended")
2166+
return
2167+
}
2168+
self.events.append(.activityEmittedData(ruleInfo: ruleInfo, data))
21602169
}
21612170
}
21622171

Tests/SWBBuildSystemTests/ClangCompilationCachingTests.swift

+2
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ fileprivate struct ClangCompilationCachingTests: CoreBasedTests {
234234
// Make sure scanning happens before compilation...
235235
results.check(event: .taskHadEvent(scanTask, event: .completed), precedes: .taskHadEvent(compileTask, event: .started))
236236

237+
results.check(contains: .activityEmittedData(ruleInfo: "CompilationCacheMetrics", ByteString(encodingAsUTF8: "Clang compiler: 0 hits (0%), 1 miss").bytes))
237238
results.checkCompileCacheMiss(compileTask)
238239
results.checkNoDiagnostics()
239240
}
@@ -261,6 +262,7 @@ fileprivate struct ClangCompilationCachingTests: CoreBasedTests {
261262
// Make sure scanning happens before compilation.
262263
results.check(event: .taskHadEvent(scanTask, event: .completed), precedes: .taskHadEvent(compileTask, event: .started))
263264

265+
results.check(contains: .activityEmittedData(ruleInfo: "CompilationCacheMetrics", ByteString(encodingAsUTF8: "Clang compiler: 1 hit (100%), 0 misses").bytes))
264266
results.checkCompileCacheHit(compileTask)
265267
}
266268
results.checkNoDiagnostics()

Tests/SWBBuildSystemTests/SwiftCompilationCachingTests.swift

+5-1
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ fileprivate struct SwiftCompilationCachingTests: CoreBasedTests {
109109
numCompile += tasks.count
110110
}
111111

112+
results.check(contains: .activityEmittedData(ruleInfo: "CompilationCacheMetrics", ByteString(encodingAsUTF8: "Swift compiler: 0 hits (0%), 4 misses").bytes))
113+
112114
results.checkNoTask()
113115
}
114116
#expect(try readMetrics("one").contains("\"swiftCacheHits\":0,\"swiftCacheMisses\":\(numCompile)"))
@@ -118,7 +120,9 @@ fileprivate struct SwiftCompilationCachingTests: CoreBasedTests {
118120
try await tester.checkBuild(runDestination: .macOS, buildCommand: .cleanBuildFolder(style: .regular), body: { _ in })
119121

120122
tester.userInfo = rawUserInfo.withAdditionalEnvironment(environment: metricsEnv("two"))
121-
try await tester.checkBuild(runDestination: .anyiOSDevice, persistent: true) { _ in }
123+
try await tester.checkBuild(runDestination: .anyiOSDevice, persistent: true) { results in
124+
results.check(contains: .activityEmittedData(ruleInfo: "CompilationCacheMetrics", ByteString(encodingAsUTF8: "Swift compiler: 4 hits (100%), 0 misses").bytes))
125+
}
122126
#expect(try readMetrics("two").contains("\"swiftCacheHits\":\(numCompile),\"swiftCacheMisses\":0"))
123127
}
124128
}

0 commit comments

Comments
 (0)