From 898d8c085dc78324304218ca44175a0001cf60e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20R=C3=B6nnqvist?= Date: Wed, 24 Sep 2025 12:12:57 +0200 Subject: [PATCH] Update the bin/benchmark script to Swift 6 --- bin/benchmark/Package.swift | 4 +- .../benchmark/BenchmarkResultSeries.swift | 2 +- .../Sources/benchmark/Commands.swift | 7 ++- .../Sources/benchmark/Diff/DiffAnalysis.swift | 4 ++ .../benchmark/Diff/DiffResultsTable.swift | 63 ++++++++++++++----- .../Subcommands/CommitCommands.swift | 3 +- .../Sources/benchmark/Subcommands/Diff.swift | 11 ++-- .../benchmark/Subcommands/Measure.swift | 4 +- .../benchmark/Subcommands/RenderTrend.swift | 5 +- 9 files changed, 73 insertions(+), 30 deletions(-) diff --git a/bin/benchmark/Package.swift b/bin/benchmark/Package.swift index 7d52848664..046395b282 100644 --- a/bin/benchmark/Package.swift +++ b/bin/benchmark/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version: 5.5 +// swift-tools-version: 6.0 /* This source file is part of the Swift.org open source project @@ -14,7 +14,7 @@ import PackageDescription let package = Package( name: "benchmark", platforms: [ - .macOS(.v12) + .macOS(.v13) ], products: [ .executable( diff --git a/bin/benchmark/Sources/benchmark/BenchmarkResultSeries.swift b/bin/benchmark/Sources/benchmark/BenchmarkResultSeries.swift index c0f2d7582f..008a206e46 100644 --- a/bin/benchmark/Sources/benchmark/BenchmarkResultSeries.swift +++ b/bin/benchmark/Sources/benchmark/BenchmarkResultSeries.swift @@ -77,7 +77,7 @@ struct BenchmarkResultSeries: Codable, Equatable { /// The list of metrics gathered in these benchmark runs. public var metrics: [MetricSeries] - static var empty = BenchmarkResultSeries(platformName: "", timestamp: Date(), doccArguments: [], metrics: []) + static let empty = BenchmarkResultSeries(platformName: "", timestamp: Date(), doccArguments: [], metrics: []) enum Error: Swift.Error, CustomStringConvertible { case addedResultHasDifferentConfiguration diff --git a/bin/benchmark/Sources/benchmark/Commands.swift b/bin/benchmark/Sources/benchmark/Commands.swift index 3c41f28a27..4eb1fff713 100644 --- a/bin/benchmark/Sources/benchmark/Commands.swift +++ b/bin/benchmark/Sources/benchmark/Commands.swift @@ -12,15 +12,16 @@ import ArgumentParser import Foundation @main -struct BenchmarkCommand: ParsableCommand { - static var configuration = CommandConfiguration( +struct BenchmarkCommand: @MainActor ParsableCommand { + @MainActor + static let configuration = CommandConfiguration( abstract: "A utility for performing benchmarks for Swift-DocC.", subcommands: [Measure.self, Diff.self, CompareTo.self, MeasureCommits.self, RenderTrend.self], defaultSubcommand: Measure.self) } let doccProjectRootURL: URL = { - let url = URL(fileURLWithPath: #file) + let url = URL(fileURLWithPath: #filePath) .deletingLastPathComponent() // Commands.swift .deletingLastPathComponent() // benchmark .deletingLastPathComponent() // Sources diff --git a/bin/benchmark/Sources/benchmark/Diff/DiffAnalysis.swift b/bin/benchmark/Sources/benchmark/Diff/DiffAnalysis.swift index cffe3e6c49..a6874188da 100644 --- a/bin/benchmark/Sources/benchmark/Diff/DiffAnalysis.swift +++ b/bin/benchmark/Sources/benchmark/Diff/DiffAnalysis.swift @@ -22,6 +22,7 @@ extension DiffResults { } } + @MainActor static func analyze(before beforeMetric: BenchmarkResultSeries.MetricSeries?, after afterMetric: BenchmarkResultSeries.MetricSeries) throws -> DiffResults.MetricAnalysis { guard let beforeMetric else { return DiffResults.MetricAnalysis( @@ -129,6 +130,7 @@ extension DiffResults { ) } + @MainActor private static func inputBiasDescription(metric: BenchmarkResultSeries.MetricSeries, sampleName: String, numbers: [Double]) -> String { // Turn the single metric series into an array of single values metric series to render the trend bars. @@ -164,6 +166,7 @@ extension DiffResults { } extension BenchmarkResultSeries.MetricSeries.ValueSeries { + @MainActor func formatted() -> String { switch self { case .duration(let value): @@ -190,6 +193,7 @@ extension BenchmarkResultSeries.MetricSeries.ValueSeries { } #if os(macOS) || os(iOS) +@MainActor private let durationFormatter: MeasurementFormatter = { let fmt = MeasurementFormatter() fmt.unitStyle = .medium diff --git a/bin/benchmark/Sources/benchmark/Diff/DiffResultsTable.swift b/bin/benchmark/Sources/benchmark/Diff/DiffResultsTable.swift index be8c39db52..2060053326 100644 --- a/bin/benchmark/Sources/benchmark/Diff/DiffResultsTable.swift +++ b/bin/benchmark/Sources/benchmark/Diff/DiffResultsTable.swift @@ -11,18 +11,40 @@ import Foundation struct DiffResultsTable { - static var columns: [(name: String, width: Int)] = [ - ("Metric", 40), - ("Change", 15), - ("Before", 20), - ("After", 20), - ] - static var totalWidth: Int { - return columns.reduce(0, { $0 + $1.width + 3 }) - 1 + struct Columns { + typealias Column = (name: String, width: Int) + var data: [Column] + + init() { + data = [ + ("Metric", 40), + ("Change", 15), + ("Before", 20), + ("After", 20), + ] + } + + var beforeInfo: Column { + get { data[2] } + set { data[2] = newValue } + } + + var afterInfo: Column { + get { data[3] } + set { data[3] = newValue } + } + + var totalWidth: Int { + data.reduce(0, { $0 + $1.width + 3 }) - 1 + } + + var names: [String] { + data.map { $0.name } + } } private(set) var output: String - init(results: DiffResults) { + init(results: DiffResults, columns: Columns) { var output = "" let allWarnings = results.analysis.flatMap { $0.warnings ?? [] } @@ -30,9 +52,10 @@ struct DiffResultsTable { output += "\(warning)\n" } - output += "┌\(String(repeating: "─", count: Self.totalWidth))┐\n" - output += Self.formattedRow(columnValues: Self.columns.map { $0.name }) - output += "├\(String(repeating: "─", count: Self.totalWidth))┤\n" + let totalWidth = columns.totalWidth + output += "┌\(String(repeating: "─", count: totalWidth))┐\n" + output += Self.formattedRow(columns: columns) + output += "├\(String(repeating: "─", count: totalWidth))┤\n" var footnoteCounter = 0 @@ -61,10 +84,16 @@ struct DiffResultsTable { footnoteCounter += footnotes.count } - output += Self.formattedRow(columnValues: [analysis.metricName, change, analysis.before ?? "-", analysis.after], colorInfo: colorInfo) + var analysisColumns = columns + analysisColumns.data[0].name = analysis.metricName + analysisColumns.data[1].name = change + analysisColumns.data[2].name = analysis.before ?? "-" + analysisColumns.data[3].name = analysis.after + + output += Self.formattedRow(columns: analysisColumns, colorInfo: colorInfo) } - output += "└\(String(repeating: "─", count: Self.totalWidth))┘\n" + output += "└\(String(repeating: "─", count: totalWidth))┘\n" let allFootnotes = results.analysis.flatMap { $0.footnotes ?? [] } if !allFootnotes.isEmpty { @@ -117,9 +146,9 @@ struct DiffResultsTable { let upTo: String.Index } - private static func formattedRow(columnValues: [String], colorInfo: [ColumnColorInfo] = []) -> String { - let values: [String] = columnValues.enumerated().map { (index, value) in - let row = value.padding(toLength: Self.columns[index].width, withPad: " ", startingAt: 0) + private static func formattedRow(columns: Columns, colorInfo: [ColumnColorInfo] = []) -> String { + let values: [String] = columns.names.enumerated().map { (index, value) in + let row = value.padding(toLength: columns.data[index].width, withPad: " ", startingAt: 0) if let colorInfo = colorInfo.first(where: { $0.index == index }) { return String(row[.. String { var output = ""