-
Notifications
You must be signed in to change notification settings - Fork 84
feat: Add PerformanceTests #1910
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
Changes from 7 commits
597be9d
9a94a6b
c0fed01
23f311f
93f94ca
d2dfeed
08c6b29
5900dd9
70d8d33
853b5d0
b7e9ad4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// swift-tools-version: 5.9 | ||
|
||
import PackageDescription | ||
|
||
let package = Package( | ||
name: "SDKWorkbench", | ||
platforms: [.macOS(.v12), .iOS(.v15)], | ||
dependencies: [ | ||
.package(name: "aws-sdk-swift", path: "../../aws-sdk-swift"), | ||
], | ||
targets: [ | ||
.executableTarget( | ||
name: "PerformanceTestRunner", | ||
dependencies: [ | ||
.product(name: "AWSSTS", package: "aws-sdk-swift"), | ||
] | ||
), | ||
] | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
// | ||
// Copyright Amazon.com Inc. or its affiliates. | ||
// All Rights Reserved. | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
|
||
struct Dimension: Codable { | ||
let name: String | ||
let value: String | ||
jbelkins marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
// | ||
// Copyright Amazon.com Inc. or its affiliates. | ||
// All Rights Reserved. | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
|
||
protocol PerformanceTest { | ||
var name: String { get } | ||
var description: String { get } | ||
var unit: Unit { get } | ||
var dimensions: [Dimension] { get } | ||
var test: () async throws -> Double { get } | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
// | ||
// Copyright Amazon.com Inc. or its affiliates. | ||
// All Rights Reserved. | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
|
||
import Foundation | ||
|
||
struct PerformanceTestReport: Codable { | ||
var productId: String = "AWS SDK for Swift" | ||
let sdkVersion: String? | ||
let commitId: String | ||
let results: [PerformanceTestResult] | ||
} | ||
|
||
extension PerformanceTestReport { | ||
func printFormatted() { | ||
let jsonEncoder = JSONEncoder() | ||
jsonEncoder.outputFormatting = .prettyPrinted | ||
|
||
if let jsonData = try? jsonEncoder.encode(self), | ||
let jsonString = String(data: jsonData, encoding: .utf8) { | ||
print(jsonString) | ||
} else { | ||
print("Error encoding JSON") | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// | ||
// Copyright Amazon.com Inc. or its affiliates. | ||
// All Rights Reserved. | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
|
||
struct PerformanceTestResult: Codable { | ||
let name: String | ||
let description: String | ||
let unit: String | ||
let date: Int | ||
let measurements: [Double] | ||
let dimensions: [Dimension]? | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// | ||
// Copyright Amazon.com Inc. or its affiliates. | ||
// All Rights Reserved. | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
|
||
enum Unit: String { | ||
jbelkins marked this conversation as resolved.
Show resolved
Hide resolved
|
||
case operationsPerSecond = "Operations/Second" | ||
case bitsPerSecond = "Bits/Second" | ||
case megabitsPerSecond = "Megabits/Second" | ||
case gigabitsPerSecond = "Gigabits/Second" | ||
case seconds = "Seconds" | ||
case milliseconds = "Milliseconds" | ||
case microseconds = "Microseconds" | ||
case nanoseconds = "Nanoseconds" | ||
case bytes = "Bytes" | ||
case megabytes = "Megabytes" | ||
case gigabytes = "Gigabytes" | ||
case percentage = "Percentage" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// | ||
// Copyright Amazon.com Inc. or its affiliates. | ||
// All Rights Reserved. | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
|
||
import Foundation | ||
|
||
struct PerformanceTestRunner { | ||
|
||
var iterations: Int | ||
|
||
/// Executes the given test multiple times | ||
func runTest( | ||
_ perfTest: PerformanceTest | ||
) async throws -> PerformanceTestResult { | ||
var measurements: [Double] = [] | ||
|
||
for _ in 0..<iterations { | ||
measurements.append(try await perfTest.test()) | ||
} | ||
jbelkins marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
let timestamp = Int(Date().timeIntervalSince1970) | ||
return PerformanceTestResult( | ||
name: perfTest.name, | ||
description: perfTest.description, | ||
unit: perfTest.unit.rawValue, | ||
date: timestamp, | ||
measurements: measurements, | ||
dimensions: perfTest.dimensions | ||
) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// | ||
// Copyright Amazon.com Inc. or its affiliates. | ||
// All Rights Reserved. | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
|
||
import Foundation | ||
|
||
struct ProcessRunner { | ||
static func runProcess( | ||
executable: String = "/usr/bin/env", | ||
arguments: [String] | ||
) -> String { | ||
let process = Process() | ||
process.executableURL = URL(fileURLWithPath: executable) | ||
process.arguments = arguments | ||
|
||
let outputPipe = Pipe() | ||
process.standardOutput = outputPipe | ||
process.standardError = Pipe() | ||
|
||
do { | ||
try process.run() | ||
process.waitUntilExit() | ||
let outputData = outputPipe.fileHandleForReading.readDataToEndOfFile() | ||
return String(data: outputData, encoding: .utf8)?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" | ||
} catch { | ||
print("ProcessRunner Error: \(error.localizedDescription)") | ||
return "" | ||
} | ||
} | ||
|
||
/// Retrieves the current Git commit ID. | ||
static func getGitCommitId() -> String { | ||
return ProcessRunner.runProcess(arguments: ["git", "rev-parse", "HEAD"]) | ||
} | ||
|
||
/// Retrieves the SDK version from a file. | ||
static func getSdkVersion() -> String { | ||
return ProcessRunner.runProcess(arguments: ["cat", "../../aws-sdk-swift/Package.version"]) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we do it elsewhere, but for safety maybe trim leading & trailing whitespace before returning version string |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// | ||
// Copyright Amazon.com Inc. or its affiliates. | ||
// All Rights Reserved. | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
|
||
enum OperatingSystem: String { | ||
case macOS = "macOS" | ||
case Linux = "Linux" | ||
case Unknown = "Unknown" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: cases of a Swift enum should start with lower case ( |
||
|
||
static var current: OperatingSystem { | ||
#if os(macOS) | ||
return .macOS | ||
#elseif os(Linux) | ||
return .Linux | ||
#else | ||
return .Unknown | ||
#endif | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
// | ||
// Copyright Amazon.com Inc. or its affiliates. | ||
// All Rights Reserved. | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
|
||
import Foundation | ||
import ClientRuntime | ||
|
||
// MARK: - Main Entry Point | ||
@main | ||
struct PerformanceMain { | ||
static func main() async throws { | ||
let runner = PerformanceTestRunner(iterations: 5) | ||
let commitId = ProcessRunner.getGitCommitId() | ||
let sdkVersion = ProcessRunner.getSdkVersion() | ||
|
||
// Add more tests here | ||
let performanceTests = [ | ||
AWSSTSGetCallerIdentity() | ||
] | ||
|
||
var results: [PerformanceTestResult] = [] | ||
for test in performanceTests { | ||
let result = try await runner.runTest(test) | ||
results.append(result) | ||
} | ||
jbelkins marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
let report = PerformanceTestReport( | ||
sdkVersion: sdkVersion, | ||
commitId: commitId, | ||
results: results | ||
) | ||
report.printFormatted() | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// | ||
// Copyright Amazon.com Inc. or its affiliates. | ||
// All Rights Reserved. | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
|
||
import AWSSTS | ||
import Foundation | ||
|
||
struct AWSSTSGetCallerIdentity: PerformanceTest { | ||
let name = "sts.getcalleridentity.latency" | ||
|
||
let description = "The total time between initiating a GetCallerIdentity and reading the last byte of the object." | ||
|
||
let unit = Unit.milliseconds | ||
|
||
let dimensions = [ | ||
Dimension(name: "OS", value: OperatingSystem.current.rawValue), | ||
] | ||
|
||
let test = getCallerIdentity | ||
jbelkins marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
static func getCallerIdentity() async throws -> Double { | ||
let start = Date() | ||
let client = try await STSClient() | ||
_ = try await client.getCallerIdentity(input: .init()) | ||
return Date().timeIntervalSince(start) * 1000 // Convert seconds to milliseconds | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.