From d95de2e3621c59cc6b17f14599d6ab7cd8c8d493 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Wed, 17 Apr 2024 17:13:40 +0100 Subject: [PATCH 1/3] Add simple synthentic modules graph benchmarks --- .../PackageGraphBenchmarks.swift | 83 ++++++++++++++++++- Benchmarks/README.md | 17 ++-- ...aphBenchmarks.PackageGraphLoading.p90.json | 4 - ...arks.SwiftPMWorkspaceModulesGraph.p90.json | 4 + ...hBenchmarks.SyntheticModulesGraph.p90.json | 4 + .../FileSystem/FileSystem+Extensions.swift | 46 ++++++++++ Sources/Basics/Graph/DirectedGraph.swift | 12 +-- Sources/Basics/Graph/UndirectedGraph.swift | 9 +- Sources/Basics/Observability.swift | 4 + Sources/PackageGraph/ModulesGraph.swift | 49 +++++++++++ .../SPMTestSupport/MockPackageGraphs.swift | 11 ++- Sources/SPMTestSupport/Observability.swift | 4 - Sources/SPMTestSupport/misc.swift | 49 +---------- .../Graph/DirectedGraphTests.swift | 4 +- .../Graph/UndirectedGraphTests.swift | 4 +- Tests/BuildTests/BuildPlanTests.swift | 2 + .../LLBuildManifestBuilderTests.swift | 3 + .../BuildTests/ModuleAliasingBuildTests.swift | 3 + .../ProductBuildDescriptionTests.swift | 4 +- .../MermaidPackageSerializerTests.swift | 5 +- Tests/CommandsTests/PackageCommandTests.swift | 3 + .../SwiftCommandStateTests.swift | 4 + .../PackageGraphPerfTests.swift | 3 + .../PackageGraphTests/ModulesGraphTests.swift | 3 + .../XCBuildSupportTests/PIFBuilderTests.swift | 3 + 25 files changed, 260 insertions(+), 77 deletions(-) delete mode 100644 Benchmarks/Thresholds/PackageGraphBenchmarks.PackageGraphLoading.p90.json create mode 100644 Benchmarks/Thresholds/macosx-arm64/PackageGraphBenchmarks.SwiftPMWorkspaceModulesGraph.p90.json create mode 100644 Benchmarks/Thresholds/macosx-arm64/PackageGraphBenchmarks.SyntheticModulesGraph.p90.json diff --git a/Benchmarks/Benchmarks/PackageGraphBenchmarks/PackageGraphBenchmarks.swift b/Benchmarks/Benchmarks/PackageGraphBenchmarks/PackageGraphBenchmarks.swift index 4846f30d80a..1c4d38061e4 100644 --- a/Benchmarks/Benchmarks/PackageGraphBenchmarks/PackageGraphBenchmarks.swift +++ b/Benchmarks/Benchmarks/PackageGraphBenchmarks/PackageGraphBenchmarks.swift @@ -1,7 +1,13 @@ +@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) import Basics import Benchmark import Foundation import PackageModel + +@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) +import func PackageGraph.loadModulesGraph + +import class TSCBasic.InMemoryFileSystem import Workspace let benchmarks = { @@ -16,6 +22,32 @@ let benchmarks = { ] } + let modulesGraphDepth: Int + if let envVar = ProcessInfo.processInfo.environment["SWIFTPM_BENCHMARK_MODULES_GRAPH_DEPTH"], + let parsedValue = Int(envVar) { + modulesGraphDepth = parsedValue + } else { + modulesGraphDepth = 100 + } + + let modulesGraphWidth: Int + if let envVar = ProcessInfo.processInfo.environment["SWIFTPM_BENCHMARK_MODULES_GRAPH_WIDTH"], + let parsedValue = Int(envVar) { + modulesGraphWidth = parsedValue + } else { + modulesGraphWidth = 100 + } + + let packagesGraphDepth: Int + if let envVar = ProcessInfo.processInfo.environment["SWIFTPM_BENCHMARK_PACKAGES_GRAPH_DEPTH"], + let parsedValue = Int(envVar) { + packagesGraphDepth = parsedValue + } else { + packagesGraphDepth = 10 + } + + let noopObservability = ObservabilitySystem.NOOP + // Benchmarks computation of a resolved graph of modules for a package using `Workspace` as an entry point. It runs PubGrub to get // resolved concrete versions of dependencies, assigning all modules and products to each other as corresponding dependencies // with their build triples, but with the build plan not yet constructed. In this benchmark specifically we're loading `Package.swift` @@ -33,10 +65,57 @@ let benchmarks = { ) { benchmark in let path = try AbsolutePath(validating: #file).parentDirectory.parentDirectory.parentDirectory let workspace = try Workspace(fileSystem: localFileSystem, location: .init(forRootPackage: path, fileSystem: localFileSystem)) - let system = ObservabilitySystem { _, _ in } for _ in benchmark.scaledIterations { - try workspace.loadPackageGraph(rootPath: path, observabilityScope: system.topScope) + try workspace.loadPackageGraph(rootPath: path, observabilityScope: noopObservability) + } + } + + + // Benchmarks computation of a resolved graph of modules for a synthesized package using `loadModulesGraph` as an + // entry point, which almost immediately delegates to `ModulesGraph.load` under the hood. + Benchmark( + "SyntheticModulesGraph", + configuration: .init( + metrics: defaultMetrics, + maxDuration: .seconds(10), + thresholds: [ + .mallocCountTotal: .init(absolute: [.p90: 2500]), + .syscalls: .init(absolute: [.p90: 0]), + ] + ) + ) { benchmark in + let targets = try (0.. { - init(nodes: [Node]) { +@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) +public struct DirectedGraph { + public init(nodes: [Node]) { self.nodes = nodes self.edges = .init(repeating: [], count: nodes.count) } - private var nodes: [Node] + public private(set) var nodes: [Node] private var edges: [[Int]] - mutating func addEdge(source: Int, destination: Int) { + public mutating func addEdge(source: Int, destination: Int) { self.edges[source].append(destination) } @@ -31,7 +32,8 @@ struct DirectedGraph { /// - source: `Index` of a node to start traversing edges from. /// - destination: `Index` of a node to which a path could exist via edges from `source`. /// - Returns: `true` if a path from `source` to `destination` exists, `false` otherwise. - func areNodesConnected(source: Int, destination: Int) -> Bool { + @_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) + public func areNodesConnected(source: Int, destination: Int) -> Bool { var todo = Deque([source]) var done = Set() diff --git a/Sources/Basics/Graph/UndirectedGraph.swift b/Sources/Basics/Graph/UndirectedGraph.swift index 02a0bdca90c..87fda92d854 100644 --- a/Sources/Basics/Graph/UndirectedGraph.swift +++ b/Sources/Basics/Graph/UndirectedGraph.swift @@ -13,8 +13,9 @@ import struct DequeModule.Deque /// Undirected graph that stores edges in an [adjacency matrix](https://en.wikipedia.org/wiki/Adjacency_list). -struct UndirectedGraph { - init(nodes: [Node]) { +@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) +public struct UndirectedGraph { + public init(nodes: [Node]) { self.nodes = nodes self.edges = .init(rows: nodes.count, columns: nodes.count) } @@ -22,7 +23,7 @@ struct UndirectedGraph { private var nodes: [Node] private var edges: AdjacencyMatrix - mutating func addEdge(source: Int, destination: Int) { + public mutating func addEdge(source: Int, destination: Int) { // Adjacency matrix is symmetrical for undirected graphs. self.edges[source, destination] = true self.edges[destination, source] = true @@ -33,7 +34,7 @@ struct UndirectedGraph { /// - source: `Index` of a node to start traversing edges from. /// - destination: `Index` of a node to which a connection could exist via edges from `source`. /// - Returns: `true` if a path from `source` to `destination` exists, `false` otherwise. - func areNodesConnected(source: Int, destination: Int) -> Bool { + public func areNodesConnected(source: Int, destination: Int) -> Bool { var todo = Deque([source]) var done = Set() diff --git a/Sources/Basics/Observability.swift b/Sources/Basics/Observability.swift index 2567c6be7ec..8a5afc23a70 100644 --- a/Sources/Basics/Observability.swift +++ b/Sources/Basics/Observability.swift @@ -56,6 +56,10 @@ public class ObservabilitySystem { self.underlying(scope, diagnostic) } } + + public static var NOOP: ObservabilityScope { + ObservabilitySystem { _, _ in }.topScope + } } public protocol ObservabilityHandlerProvider { diff --git a/Sources/PackageGraph/ModulesGraph.swift b/Sources/PackageGraph/ModulesGraph.swift index fdf206d84e5..edd4bf67853 100644 --- a/Sources/PackageGraph/ModulesGraph.swift +++ b/Sources/PackageGraph/ModulesGraph.swift @@ -10,6 +10,8 @@ // //===----------------------------------------------------------------------===// +import protocol Basics.FileSystem +import class Basics.ObservabilityScope import struct Basics.IdentifiableSet import OrderedCollections import PackageLoading @@ -382,3 +384,50 @@ func topologicalSort( return result.reversed() } + +@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) +public func loadModulesGraph( + identityResolver: IdentityResolver = DefaultIdentityResolver(), + fileSystem: FileSystem, + manifests: [Manifest], + binaryArtifacts: [PackageIdentity: [String: BinaryArtifact]] = [:], + explicitProduct: String? = .none, + shouldCreateMultipleTestProducts: Bool = false, + createREPLProduct: Bool = false, + useXCBuildFileRules: Bool = false, + customXCTestMinimumDeploymentTargets: [PackageModel.Platform: PlatformVersion]? = .none, + observabilityScope: ObservabilityScope +) throws -> ModulesGraph { + let rootManifests = manifests.filter(\.packageKind.isRoot).spm_createDictionary { ($0.path, $0) } + let externalManifests = try manifests.filter { !$0.packageKind.isRoot } + .reduce( + into: OrderedCollections + .OrderedDictionary() + ) { partial, item in + partial[try identityResolver.resolveIdentity(for: item.packageKind)] = (item, fileSystem) + } + + let packages = Array(rootManifests.keys) + let input = PackageGraphRootInput(packages: packages) + let graphRoot = PackageGraphRoot( + input: input, + manifests: rootManifests, + explicitProduct: explicitProduct, + observabilityScope: observabilityScope + ) + + return try ModulesGraph.load( + root: graphRoot, + identityResolver: identityResolver, + additionalFileRules: useXCBuildFileRules ? FileRuleDescription.xcbuildFileTypes : FileRuleDescription + .swiftpmFileTypes, + externalManifests: externalManifests, + binaryArtifacts: binaryArtifacts, + shouldCreateMultipleTestProducts: shouldCreateMultipleTestProducts, + createREPLProduct: createREPLProduct, + customXCTestMinimumDeploymentTargets: customXCTestMinimumDeploymentTargets, + availableLibraries: [], + fileSystem: fileSystem, + observabilityScope: observabilityScope + ) +} diff --git a/Sources/SPMTestSupport/MockPackageGraphs.swift b/Sources/SPMTestSupport/MockPackageGraphs.swift index 3f7b77ec353..2865fc2bf88 100644 --- a/Sources/SPMTestSupport/MockPackageGraphs.swift +++ b/Sources/SPMTestSupport/MockPackageGraphs.swift @@ -13,7 +13,12 @@ import struct Basics.AbsolutePath import class Basics.ObservabilitySystem import class Basics.ObservabilityScope + import struct PackageGraph.ModulesGraph + +@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) +import func PackageGraph.loadModulesGraph + import class PackageModel.Manifest import struct PackageModel.ProductDescription import struct PackageModel.TargetDescription @@ -39,7 +44,7 @@ package func macrosPackageGraph() throws -> MockPackageGraph { ) let observability = ObservabilitySystem.makeForTesting() - let graph = try loadPackageGraph( + let graph = try loadModulesGraph( fileSystem: fs, manifests: [ Manifest.createRootManifest( @@ -134,7 +139,7 @@ package func trivialPackageGraph(pkgRootPath: AbsolutePath) throws -> MockPackag ) let observability = ObservabilitySystem.makeForTesting() - let graph = try loadPackageGraph( + let graph = try loadModulesGraph( fileSystem: fs, manifests: [ Manifest.createRootManifest( @@ -164,7 +169,7 @@ package func embeddedCxxInteropPackageGraph(pkgRootPath: AbsolutePath) throws -> ) let observability = ObservabilitySystem.makeForTesting() - let graph = try loadPackageGraph( + let graph = try loadModulesGraph( fileSystem: fs, manifests: [ Manifest.createRootManifest( diff --git a/Sources/SPMTestSupport/Observability.swift b/Sources/SPMTestSupport/Observability.swift index f997150e61a..c27349bf00d 100644 --- a/Sources/SPMTestSupport/Observability.swift +++ b/Sources/SPMTestSupport/Observability.swift @@ -24,10 +24,6 @@ extension ObservabilitySystem { let observabilitySystem = ObservabilitySystem(collector) return TestingObservability(collector: collector, topScope: observabilitySystem.topScope) } - - package static var NOOP: ObservabilityScope { - ObservabilitySystem { _, _ in }.topScope - } } package struct TestingObservability { diff --git a/Sources/SPMTestSupport/misc.swift b/Sources/SPMTestSupport/misc.swift index 8a36a09237d..5f22bf7e1e2 100644 --- a/Sources/SPMTestSupport/misc.swift +++ b/Sources/SPMTestSupport/misc.swift @@ -16,7 +16,10 @@ import struct Foundation.URL import class Foundation.Bundle #endif import OrderedCollections + +@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) import PackageGraph + import PackageLoading import PackageModel import SourceControl @@ -347,52 +350,6 @@ package func loadPackageGraph( ) } -package func loadModulesGraph( - identityResolver: IdentityResolver = DefaultIdentityResolver(), - fileSystem: FileSystem, - manifests: [Manifest], - binaryArtifacts: [PackageIdentity: [String: BinaryArtifact]] = [:], - explicitProduct: String? = .none, - shouldCreateMultipleTestProducts: Bool = false, - createREPLProduct: Bool = false, - useXCBuildFileRules: Bool = false, - customXCTestMinimumDeploymentTargets: [PackageModel.Platform: PlatformVersion]? = .none, - observabilityScope: ObservabilityScope -) throws -> ModulesGraph { - let rootManifests = manifests.filter(\.packageKind.isRoot).spm_createDictionary { ($0.path, $0) } - let externalManifests = try manifests.filter { !$0.packageKind.isRoot } - .reduce( - into: OrderedCollections - .OrderedDictionary() - ) { partial, item in - partial[try identityResolver.resolveIdentity(for: item.packageKind)] = (item, fileSystem) - } - - let packages = Array(rootManifests.keys) - let input = PackageGraphRootInput(packages: packages) - let graphRoot = PackageGraphRoot( - input: input, - manifests: rootManifests, - explicitProduct: explicitProduct, - observabilityScope: observabilityScope - ) - - return try ModulesGraph.load( - root: graphRoot, - identityResolver: identityResolver, - additionalFileRules: useXCBuildFileRules ? FileRuleDescription.xcbuildFileTypes : FileRuleDescription - .swiftpmFileTypes, - externalManifests: externalManifests, - binaryArtifacts: binaryArtifacts, - shouldCreateMultipleTestProducts: shouldCreateMultipleTestProducts, - createREPLProduct: createREPLProduct, - customXCTestMinimumDeploymentTargets: customXCTestMinimumDeploymentTargets, - availableLibraries: [], - fileSystem: fileSystem, - observabilityScope: observabilityScope - ) -} - package let emptyZipFile = ByteString([0x80, 0x75, 0x05, 0x06] + [UInt8](repeating: 0x00, count: 18)) extension FileSystem { diff --git a/Tests/BasicsTests/Graph/DirectedGraphTests.swift b/Tests/BasicsTests/Graph/DirectedGraphTests.swift index a9f177d684a..3f168cb533c 100644 --- a/Tests/BasicsTests/Graph/DirectedGraphTests.swift +++ b/Tests/BasicsTests/Graph/DirectedGraphTests.swift @@ -10,7 +10,9 @@ // //===----------------------------------------------------------------------===// -@testable import Basics +@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) +import Basics + import XCTest final class DirectedGraphTests: XCTestCase { diff --git a/Tests/BasicsTests/Graph/UndirectedGraphTests.swift b/Tests/BasicsTests/Graph/UndirectedGraphTests.swift index f5c0f812100..0ec595e6d91 100644 --- a/Tests/BasicsTests/Graph/UndirectedGraphTests.swift +++ b/Tests/BasicsTests/Graph/UndirectedGraphTests.swift @@ -10,7 +10,9 @@ // //===----------------------------------------------------------------------===// -@testable import Basics +@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) +import Basics + import XCTest final class UndirectedGraphTests: XCTestCase { diff --git a/Tests/BuildTests/BuildPlanTests.swift b/Tests/BuildTests/BuildPlanTests.swift index 0fbbab8b6c9..341c0367067 100644 --- a/Tests/BuildTests/BuildPlanTests.swift +++ b/Tests/BuildTests/BuildPlanTests.swift @@ -16,7 +16,9 @@ @testable import DriverSupport +@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) @testable import PackageGraph + import PackageLoading @testable import PackageModel import SPMBuildCore diff --git a/Tests/BuildTests/LLBuildManifestBuilderTests.swift b/Tests/BuildTests/LLBuildManifestBuilderTests.swift index c9119b0a919..4c3b29e0dff 100644 --- a/Tests/BuildTests/LLBuildManifestBuilderTests.swift +++ b/Tests/BuildTests/LLBuildManifestBuilderTests.swift @@ -13,7 +13,10 @@ import Basics @testable import Build import LLBuildManifest + +@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) import PackageGraph + import PackageModel import struct SPMBuildCore.BuildParameters diff --git a/Tests/BuildTests/ModuleAliasingBuildTests.swift b/Tests/BuildTests/ModuleAliasingBuildTests.swift index 23244d40a5a..4491da338a1 100644 --- a/Tests/BuildTests/ModuleAliasingBuildTests.swift +++ b/Tests/BuildTests/ModuleAliasingBuildTests.swift @@ -12,7 +12,10 @@ import Basics @testable import Build + +@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) @testable import PackageGraph + import PackageLoading @testable import PackageModel import SPMBuildCore diff --git a/Tests/BuildTests/ProductBuildDescriptionTests.swift b/Tests/BuildTests/ProductBuildDescriptionTests.swift index f07646f64a5..fb576a5aac0 100644 --- a/Tests/BuildTests/ProductBuildDescriptionTests.swift +++ b/Tests/BuildTests/ProductBuildDescriptionTests.swift @@ -22,7 +22,9 @@ import struct PackageModel.TargetDescription @testable import struct PackageGraph.ResolvedProduct -import func SPMTestSupport.loadModulesGraph +@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) +import func PackageGraph.loadModulesGraph + import func SPMTestSupport.mockBuildParameters import func SPMTestSupport.XCTAssertNoDiagnostics import XCTest diff --git a/Tests/CommandsTests/MermaidPackageSerializerTests.swift b/Tests/CommandsTests/MermaidPackageSerializerTests.swift index f8524d28c04..2c5f88cd415 100644 --- a/Tests/CommandsTests/MermaidPackageSerializerTests.swift +++ b/Tests/CommandsTests/MermaidPackageSerializerTests.swift @@ -11,11 +11,14 @@ //===----------------------------------------------------------------------===// import class Basics.ObservabilitySystem + +@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) +import func PackageGraph.loadModulesGraph + import class PackageModel.Manifest import struct PackageModel.ProductDescription import struct PackageModel.TargetDescription import class TSCBasic.InMemoryFileSystem -import func SPMTestSupport.loadModulesGraph import func SPMTestSupport.XCTAssertNoDiagnostics @testable diff --git a/Tests/CommandsTests/PackageCommandTests.swift b/Tests/CommandsTests/PackageCommandTests.swift index 73e2d58db2d..8ac0223cd69 100644 --- a/Tests/CommandsTests/PackageCommandTests.swift +++ b/Tests/CommandsTests/PackageCommandTests.swift @@ -19,7 +19,10 @@ import CoreCommands import Commands import Foundation + +@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) import PackageGraph + import PackageLoading import PackageModel import SourceControl diff --git a/Tests/CommandsTests/SwiftCommandStateTests.swift b/Tests/CommandsTests/SwiftCommandStateTests.swift index b1d0b8fdfcc..c0cafa40d91 100644 --- a/Tests/CommandsTests/SwiftCommandStateTests.swift +++ b/Tests/CommandsTests/SwiftCommandStateTests.swift @@ -17,6 +17,10 @@ import CoreCommands @testable import Commands + +@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) +import func PackageGraph.loadModulesGraph + @testable import PackageModel import SPMTestSupport import XCTest diff --git a/Tests/PackageGraphPerformanceTests/PackageGraphPerfTests.swift b/Tests/PackageGraphPerformanceTests/PackageGraphPerfTests.swift index c688b1d5439..18d52e71f3a 100644 --- a/Tests/PackageGraphPerformanceTests/PackageGraphPerfTests.swift +++ b/Tests/PackageGraphPerformanceTests/PackageGraphPerfTests.swift @@ -12,7 +12,10 @@ import Basics import OrderedCollections + +@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) import PackageGraph + import PackageLoading import PackageModel import SPMTestSupport diff --git a/Tests/PackageGraphTests/ModulesGraphTests.swift b/Tests/PackageGraphTests/ModulesGraphTests.swift index 420387d5d7d..16c86130bbc 100644 --- a/Tests/PackageGraphTests/ModulesGraphTests.swift +++ b/Tests/PackageGraphTests/ModulesGraphTests.swift @@ -11,7 +11,10 @@ //===----------------------------------------------------------------------===// import Basics + +@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) @testable import PackageGraph + import PackageModel import SPMTestSupport import XCTest diff --git a/Tests/XCBuildSupportTests/PIFBuilderTests.swift b/Tests/XCBuildSupportTests/PIFBuilderTests.swift index c03033ecb9f..7acf0279ef4 100644 --- a/Tests/XCBuildSupportTests/PIFBuilderTests.swift +++ b/Tests/XCBuildSupportTests/PIFBuilderTests.swift @@ -12,7 +12,10 @@ import Basics import Foundation + +@_spi(DontAdoptOutsideOfSwiftPMExposedForBenchmarksAndTestsOnly) import PackageGraph + @testable import PackageModel import PackageLoading import SPMBuildCore From 6910c00982ff5d64a9970c8eb1ce50767223da44 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Wed, 17 Apr 2024 18:37:15 +0100 Subject: [PATCH 2/3] Add synthetic modules graph benchmarks with macros Benchmarking modules graph is now generalized with `syntheticModulesGraph` function. It also uncovered a bug in the previous `SyntheticModulesGraph`, which didn't pass generated `TargetDescription`s array to `loadModulesGraph`, which is fixed now. New `SyntheticModulesGraphWithMacros` calls `syntheticModulesGraph` with `includeMacros: true` argument, which splits all modules in three parts: library modules, macros modules that library modules depend on, and macro dependencies that macros depend on. This allows us to track potential performance regressions in https://github.com/apple/swift-package-manager/pull/7353. --- .../PackageGraphBenchmarks.swift | 137 +++++++++++++----- ...arks.SwiftPMWorkspaceModulesGraph.p90.json | 4 +- ...hBenchmarks.SyntheticModulesGraph.p90.json | 2 +- ...s.SyntheticModulesGraphWithMacros.p90.json | 4 + 4 files changed, 107 insertions(+), 40 deletions(-) create mode 100644 Benchmarks/Thresholds/macosx-arm64/PackageGraphBenchmarks.SyntheticModulesGraphWithMacros.p90.json diff --git a/Benchmarks/Benchmarks/PackageGraphBenchmarks/PackageGraphBenchmarks.swift b/Benchmarks/Benchmarks/PackageGraphBenchmarks/PackageGraphBenchmarks.swift index 1c4d38061e4..bab1f4af582 100644 --- a/Benchmarks/Benchmarks/PackageGraphBenchmarks/PackageGraphBenchmarks.swift +++ b/Benchmarks/Benchmarks/PackageGraphBenchmarks/PackageGraphBenchmarks.swift @@ -27,7 +27,7 @@ let benchmarks = { let parsedValue = Int(envVar) { modulesGraphDepth = parsedValue } else { - modulesGraphDepth = 100 + modulesGraphDepth = 150 } let modulesGraphWidth: Int @@ -35,7 +35,7 @@ let benchmarks = { let parsedValue = Int(envVar) { modulesGraphWidth = parsedValue } else { - modulesGraphWidth = 100 + modulesGraphWidth = 150 } let packagesGraphDepth: Int @@ -46,8 +46,6 @@ let benchmarks = { packagesGraphDepth = 10 } - let noopObservability = ObservabilitySystem.NOOP - // Benchmarks computation of a resolved graph of modules for a package using `Workspace` as an entry point. It runs PubGrub to get // resolved concrete versions of dependencies, assigning all modules and products to each other as corresponding dependencies // with their build triples, but with the build plan not yet constructed. In this benchmark specifically we're loading `Package.swift` @@ -67,55 +65,120 @@ let benchmarks = { let workspace = try Workspace(fileSystem: localFileSystem, location: .init(forRootPackage: path, fileSystem: localFileSystem)) for _ in benchmark.scaledIterations { - try workspace.loadPackageGraph(rootPath: path, observabilityScope: noopObservability) + try workspace.loadPackageGraph(rootPath: path, observabilityScope: ObservabilitySystem.NOOP) } } - - // Benchmarks computation of a resolved graph of modules for a synthesized package using `loadModulesGraph` as an - // entry point, which almost immediately delegates to `ModulesGraph.load` under the hood. + // Benchmarks computation of a resolved graph of modules for a trivial synthesized package using `loadModulesGraph` + // as an entry point, which almost immediately delegates to `ModulesGraph.load` under the hood. Benchmark( "SyntheticModulesGraph", configuration: .init( metrics: defaultMetrics, maxDuration: .seconds(10), thresholds: [ - .mallocCountTotal: .init(absolute: [.p90: 2500]), - .syscalls: .init(absolute: [.p90: 0]), + .mallocCountTotal: .init(absolute: [.p90: 17000]), + .syscalls: .init(absolute: [.p90: 5]), ] ) ) { benchmark in - let targets = try (0.. TargetDescription in + let dependencies = (0.. [TargetDescription.Dependency] in + if includeMacros { + [.target(name: "Module\(i)"), .target(name: "Macros\(i)")] + } else { + [.target(name: "Module\(i)")] + } + } + return try TargetDescription(name: "Module\(i)", dependencies: dependencies) + } + + let macrosModules: [TargetDescription] + let macrosDependenciesModules: [TargetDescription] + if includeMacros { + macrosModules = try (0.. Date: Wed, 17 Apr 2024 22:23:02 +0100 Subject: [PATCH 3/3] Replace `macosx` with `macos` in benchmark thresholds The platform component name inference code for macOS was copied from `apple/swift` and is incorrect. We have to keep using `macosx` in `apple/swift` for backward compatibility, but we have no such restriction in SwiftPM benchmarks. --- Benchmarks/README.md | 2 +- ...PackageGraphBenchmarks.SwiftPMWorkspaceModulesGraph.p90.json | 0 .../PackageGraphBenchmarks.SyntheticModulesGraph.p90.json | 0 ...kageGraphBenchmarks.SyntheticModulesGraphWithMacros.p90.json | 0 4 files changed, 1 insertion(+), 1 deletion(-) rename Benchmarks/Thresholds/{macosx-arm64 => macos-arm64}/PackageGraphBenchmarks.SwiftPMWorkspaceModulesGraph.p90.json (100%) rename Benchmarks/Thresholds/{macosx-arm64 => macos-arm64}/PackageGraphBenchmarks.SyntheticModulesGraph.p90.json (100%) rename Benchmarks/Thresholds/{macosx-arm64 => macos-arm64}/PackageGraphBenchmarks.SyntheticModulesGraphWithMacros.p90.json (100%) diff --git a/Benchmarks/README.md b/Benchmarks/README.md index 8e1022adc2f..ea1b61d662e 100644 --- a/Benchmarks/README.md +++ b/Benchmarks/README.md @@ -26,7 +26,7 @@ built with Swift 5.10. To record new thresholds, run the following command: ``` swift package --allow-writing-to-package-directory benchmark \ --format metricP90AbsoluteThresholds \ - --path "Thresholds/$([[ $(uname) == Darwin ]] && echo macosx || echo linux)-$(uname -m)" + --path "Thresholds/$([[ $(uname) == Darwin ]] && echo macos || echo linux)-$(uname -m)" ``` To verify that recorded thresholds do not exceeded given relative or absolute values (passed as `thresholds` arguments diff --git a/Benchmarks/Thresholds/macosx-arm64/PackageGraphBenchmarks.SwiftPMWorkspaceModulesGraph.p90.json b/Benchmarks/Thresholds/macos-arm64/PackageGraphBenchmarks.SwiftPMWorkspaceModulesGraph.p90.json similarity index 100% rename from Benchmarks/Thresholds/macosx-arm64/PackageGraphBenchmarks.SwiftPMWorkspaceModulesGraph.p90.json rename to Benchmarks/Thresholds/macos-arm64/PackageGraphBenchmarks.SwiftPMWorkspaceModulesGraph.p90.json diff --git a/Benchmarks/Thresholds/macosx-arm64/PackageGraphBenchmarks.SyntheticModulesGraph.p90.json b/Benchmarks/Thresholds/macos-arm64/PackageGraphBenchmarks.SyntheticModulesGraph.p90.json similarity index 100% rename from Benchmarks/Thresholds/macosx-arm64/PackageGraphBenchmarks.SyntheticModulesGraph.p90.json rename to Benchmarks/Thresholds/macos-arm64/PackageGraphBenchmarks.SyntheticModulesGraph.p90.json diff --git a/Benchmarks/Thresholds/macosx-arm64/PackageGraphBenchmarks.SyntheticModulesGraphWithMacros.p90.json b/Benchmarks/Thresholds/macos-arm64/PackageGraphBenchmarks.SyntheticModulesGraphWithMacros.p90.json similarity index 100% rename from Benchmarks/Thresholds/macosx-arm64/PackageGraphBenchmarks.SyntheticModulesGraphWithMacros.p90.json rename to Benchmarks/Thresholds/macos-arm64/PackageGraphBenchmarks.SyntheticModulesGraphWithMacros.p90.json