Skip to content

Commit 48eddac

Browse files
committed
Benchmarks: Add support for async benchmarks
1 parent 2ec19ec commit 48eddac

File tree

3 files changed

+27
-21
lines changed

3 files changed

+27
-21
lines changed

benchmark/utils/DriverUtils.swift

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ import LibProc
2323

2424
import TestsUtils
2525

26+
/// Sorry.
27+
private func ??<T>(_ x: T?, _ y: @autoclosure () async -> T) async -> T {
28+
if let x { return x }
29+
return await y()
30+
}
31+
2632
struct MeasurementMetadata {
2733
// Note: maxRSS and pages subtract the RSS measured
2834
// after the benchmark driver setup has finished.
@@ -487,13 +493,13 @@ final class TestRunner {
487493
}
488494

489495
/// Measure the `fn` and return the average sample time per iteration (μs).
490-
func measure(_ name: String, fn: (Int) -> Void, numIters: Int) -> Double {
496+
func measure(_ name: String, fn: (Int) async -> Void, numIters: Int) async -> Double {
491497
#if SWIFT_RUNTIME_ENABLE_LEAK_CHECKER
492498
name.withCString { p in startTrackingObjects(p) }
493499
#endif
494500

495501
startMeasurement()
496-
fn(numIters)
502+
await fn(numIters)
497503
stopMeasurement()
498504

499505
#if SWIFT_RUNTIME_ENABLE_LEAK_CHECKER
@@ -508,7 +514,7 @@ final class TestRunner {
508514
}
509515

510516
/// Run the benchmark and return the measured results.
511-
func run(_ test: BenchmarkInfo) -> BenchResults? {
517+
func run(_ test: BenchmarkInfo) async -> BenchResults? {
512518
// Before we do anything, check that we actually have a function to
513519
// run. If we don't it is because the benchmark is not supported on
514520
// the platform and we should skip it.
@@ -534,8 +540,8 @@ final class TestRunner {
534540
}
535541

536542
// Determine number of iterations for testFn to run for desired time.
537-
func iterationsPerSampleTime() -> (numIters: Int, oneIter: Double) {
538-
let oneIter = measure(test.name, fn: testFn, numIters: 1)
543+
func iterationsPerSampleTime() async -> (numIters: Int, oneIter: Double) {
544+
let oneIter = await measure(test.name, fn: testFn, numIters: 1)
539545
if oneIter > 0 {
540546
let timePerSample = c.sampleTime * 1_000_000.0 // microseconds (μs)
541547
return (max(Int(timePerSample / oneIter), 1), oneIter)
@@ -546,28 +552,28 @@ final class TestRunner {
546552

547553
// Determine the scale of measurements. Re-use the calibration result if
548554
// it is just one measurement.
549-
func calibrateMeasurements() -> Int {
550-
let (numIters, oneIter) = iterationsPerSampleTime()
555+
func calibrateMeasurements() async -> Int {
556+
let (numIters, oneIter) = await iterationsPerSampleTime()
551557
if numIters == 1 { addSample(oneIter) }
552558
else { resetMeasurements() } // for accurate yielding reports
553559
return numIters
554560
}
555561

556562
let numIters = min( // Cap to prevent overflow on 32-bit systems when scaled
557563
Int.max / 10_000, // by the inner loop multiplier inside the `testFn`.
558-
c.numIters ?? calibrateMeasurements())
564+
await c.numIters ?? (await calibrateMeasurements()))
559565

560-
let numSamples = c.numSamples ??
566+
let numSamples = await c.numSamples ??
561567
// Compute the number of samples to measure for `sample-time`,
562568
// clamped in (`min-samples`, 200) range, if the `num-iters` are fixed.
563-
max(c.minSamples ?? 1, min(200, c.numIters == nil ? 1 :
564-
calibrateMeasurements()))
569+
(max(await c.minSamples ?? 1, min(200, c.numIters == nil ? 1 :
570+
await calibrateMeasurements())))
565571

566572
samples.reserveCapacity(numSamples)
567573
logVerbose(" Collecting \(numSamples) samples.")
568574
logVerbose(" Measuring with scale \(numIters).")
569575
for _ in samples.count..<numSamples {
570-
addSample(measure(test.name, fn: testFn, numIters: numIters))
576+
addSample(await measure(test.name, fn: testFn, numIters: numIters))
571577
}
572578

573579
test.tearDownFunction?()
@@ -687,16 +693,16 @@ final class TestRunner {
687693
}
688694

689695
/// Run each benchmark and emit the results in JSON
690-
func runBenchmarks() {
696+
func runBenchmarks() async {
691697
var testCount = 0
692698
if !c.jsonOutput {
693699
printTextHeading()
694700
}
695701
for (index, info) in c.tests {
696702
if c.jsonOutput {
697-
printJSON(index: index, info: info, results: run(info))
703+
printJSON(index: index, info: info, results: await run(info))
698704
} else {
699-
printText(index: index, info: info, results: run(info))
705+
printText(index: index, info: info, results: await run(info))
700706
}
701707
testCount += 1
702708
}
@@ -718,7 +724,7 @@ extension Hasher {
718724
}
719725
}
720726

721-
public func main() {
727+
public func main() async {
722728
let config = TestConfig(registeredBenchmarks)
723729
switch (config.action) {
724730
case .listTests:
@@ -748,7 +754,7 @@ public func main() {
748754
the option '--allow-nondeterministic-hashing to the benchmarking executable.
749755
""")
750756
}
751-
TestRunner(config).runBenchmarks()
757+
await TestRunner(config).runBenchmarks()
752758
if let x = config.afterRunSleep {
753759
sleep(x)
754760
}

benchmark/utils/TestsUtils.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,10 +116,10 @@ public struct BenchmarkInfo {
116116
public var name: String
117117

118118
/// Shadow static variable for runFunction.
119-
private var _runFunction: (Int) -> ()
119+
private var _runFunction: (Int) async -> ()
120120

121121
/// A function that invokes the specific benchmark routine.
122-
public var runFunction: ((Int) -> ())? {
122+
public var runFunction: ((Int) async -> ())? {
123123
if !shouldRun {
124124
return nil
125125
}
@@ -174,7 +174,7 @@ public struct BenchmarkInfo {
174174
/// to be interrupted by a context switch.
175175
public var legacyFactor: Int?
176176

177-
public init(name: String, runFunction: @escaping (Int) -> (), tags: [BenchmarkCategory],
177+
public init(name: String, runFunction: @escaping (Int) async -> (), tags: [BenchmarkCategory],
178178
setUpFunction: (() -> ())? = nil,
179179
tearDownFunction: (() -> ())? = nil,
180180
unsupportedPlatforms: BenchmarkPlatformSet = [],

benchmark/utils/main.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -421,4 +421,4 @@ register(Walsh.benchmarks)
421421
register(WordCount.benchmarks)
422422
register(XorLoop.benchmarks)
423423

424-
main()
424+
await main()

0 commit comments

Comments
 (0)