Skip to content

Commit bfa198b

Browse files
committed
[benchmark][Gardening] Immutable TestConfig
The `TestConfig` is now completely immutable. Arguments that are not necessary for running benchmarks were moved inside the config initialization, which also subsumed the `printRunInfo` function for displaying the configuration details in verbose mode.
1 parent 50575b1 commit bfa198b

File tree

1 file changed

+46
-46
lines changed

1 file changed

+46
-46
lines changed

benchmark/utils/DriverUtils.swift

Lines changed: 46 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,6 @@ struct TestConfig {
3434
/// The delimiter to use when printing output.
3535
let delim: String
3636

37-
/// The filters applied to our test names.
38-
let filters: [String]
39-
40-
/// The tags that we want to run
41-
let tags: Set<BenchmarkCategory>
42-
43-
/// Tests tagged with any of these will not be executed
44-
let skipTags: Set<BenchmarkCategory>
45-
4637
/// The scalar multiple of the amount of times a test should be run. This
4738
/// enables one to cause tests to run for N iterations longer than they
4839
/// normally would. This is useful when one wishes for a test to run for a
@@ -65,20 +56,20 @@ struct TestConfig {
6556
let afterRunSleep: Int?
6657

6758
/// The list of tests to run.
68-
var tests = [(index: String, info: BenchmarkInfo)]()
59+
let tests: [(index: String, info: BenchmarkInfo)]
6960

7061
let action: TestAction
7162

72-
init() throws {
63+
init(_ registeredBenchmarks: [BenchmarkInfo]) throws {
7364

7465
struct PartialTestConfig {
7566
var delim: String?
76-
var filters: [String]?
7767
var tags, skipTags: Set<BenchmarkCategory>?
7868
var iterationScale, numSamples, afterRunSleep: Int?
7969
var fixedNumIters: UInt?
8070
var verbose: Bool?
8171
var action: TestAction?
72+
var filters: [String]?
8273
}
8374
var c = PartialTestConfig()
8475

@@ -91,8 +82,6 @@ struct TestConfig {
9182
throw ArgumentError.general("Failed to parse arguments")
9283
}
9384

94-
filters = benchArgs.positionalArgs
95-
9685
func checked<T>(
9786
_ parse: (String) throws -> T?,
9887
_ value: String,
@@ -134,6 +123,7 @@ struct TestConfig {
134123
try checked({ BenchmarkCategory(rawValue: $0) }, $0) })
135124
}
136125

126+
// Parse command line arguments
137127
try optionalArg("--iter-scale", \.iterationScale) { Int($0) }
138128
try optionalArg("--num-iters", \.fixedNumIters) { UInt($0) }
139129
try optionalArg("--num-samples", \.numSamples) { Int($0) }
@@ -146,32 +136,62 @@ struct TestConfig {
146136
try optionalArg("--list", \.action, defaultValue: .listTests)
147137
try optionalArg("--help", \.action, defaultValue: .help(validOptions))
148138

139+
c.filters = benchArgs.positionalArgs
140+
149141
// Configure from the command line arguments, filling in the defaults.
150142
delim = c.delim ?? ","
151-
self.tags = c.tags ?? []
152-
skipTags = c.skipTags ?? [.unstable, .skip]
153143
iterationScale = c.iterationScale ?? 1
154144
fixedNumIters = c.fixedNumIters ?? 0
155145
numSamples = c.numSamples ?? 1
156146
verbose = c.verbose ?? false
157147
afterRunSleep = c.afterRunSleep
158148
action = c.action ?? .run
159-
// TODO: filters, tests
149+
tests = TestConfig.filterTests(registeredBenchmarks,
150+
filters: c.filters ?? [],
151+
tags: c.tags ?? [],
152+
skipTags: c.skipTags ?? [.unstable, .skip])
153+
154+
if verbose {
155+
let testList = tests.map({ $0.1.name }).joined(separator: ", ")
156+
print("""
157+
--- CONFIG ---
158+
NumSamples: \(numSamples)
159+
Verbose: \(verbose)
160+
IterScale: \(iterationScale)
161+
FixedIters: \(fixedNumIters)
162+
Tests Filter: \(c.filters ?? [])
163+
Tests to run: \(testList)
164+
165+
--- DATA ---\n
166+
""")
167+
}
160168
}
161169

162-
mutating func findTestsToRun() {
163-
registeredBenchmarks.sort()
170+
/// Returns the list of tests to run.
171+
///
172+
/// - Parameters:
173+
/// - registeredBenchmarks: List of all performance tests to be filtered.
174+
/// - filters: List of explicitly specified tests to run. These can be
175+
/// specified either by a test name or a test number.
176+
/// - tags: Run tests tagged with all of these categories.
177+
/// - skipTags: Don't run tests tagged with any of these categories.
178+
/// - Returns: An array of test number and benchmark info tuples satisfying
179+
/// specified filtering conditions.
180+
static func filterTests(
181+
_ registeredBenchmarks: [BenchmarkInfo],
182+
filters: [String],
183+
tags: Set<BenchmarkCategory>,
184+
skipTags: Set<BenchmarkCategory>
185+
) -> [(index: String, info: BenchmarkInfo)] {
164186
let indices = Dictionary(uniqueKeysWithValues:
165-
zip(registeredBenchmarks.map{ $0.name },
187+
zip(registeredBenchmarks.sorted().map{ $0.name },
166188
(1...).lazy.map { String($0) } ))
167189
let benchmarkNamesOrIndices = Set(filters)
168-
// needed so we don't capture an ivar of a mutable inout self.
169-
let (_tags, _skipTags) = (tags, skipTags)
170190

171-
tests = registeredBenchmarks.filter { benchmark in
191+
return registeredBenchmarks.filter { benchmark in
172192
if benchmarkNamesOrIndices.isEmpty {
173-
return benchmark.tags.isSuperset(of: _tags) &&
174-
benchmark.tags.isDisjoint(with: _skipTags)
193+
return benchmark.tags.isSuperset(of: tags) &&
194+
benchmark.tags.isDisjoint(with: skipTags)
175195
} else {
176196
return benchmarkNamesOrIndices.contains(benchmark.name) ||
177197
benchmarkNamesOrIndices.contains(indices[benchmark.name]!)
@@ -384,23 +404,6 @@ func runBench(_ test: BenchmarkInfo, _ c: TestConfig) -> BenchResults? {
384404
maxRSS: UInt64(sampler.measureMemoryUsage()))
385405
}
386406

387-
func printRunInfo(_ c: TestConfig) {
388-
if c.verbose {
389-
print("--- CONFIG ---")
390-
print("NumSamples: \(c.numSamples)")
391-
print("Verbose: \(c.verbose)")
392-
print("IterScale: \(c.iterationScale)")
393-
if c.fixedNumIters != 0 {
394-
print("FixedIters: \(c.fixedNumIters)")
395-
}
396-
print("Tests Filter: \(c.filters)")
397-
print("Tests to run: ", terminator: "")
398-
print(c.tests.map({ $0.1.name }).joined(separator: ", "))
399-
print("")
400-
print("--- DATA ---")
401-
}
402-
}
403-
404407
/// Execute benchmarks and continuously report the measurement results.
405408
func runBenchmarks(_ c: TestConfig) {
406409
let withUnit = {$0 + "(us)"}
@@ -440,24 +443,21 @@ func runBenchmarks(_ c: TestConfig) {
440443

441444
public func main() {
442445
do {
443-
var config = try TestConfig()
446+
let config = try TestConfig(registeredBenchmarks)
444447
switch (config.action) {
445448
case let .help(validOptions):
446449
print("Valid options:")
447450
for v in validOptions {
448451
print(" \(v)")
449452
}
450453
case .listTests:
451-
config.findTestsToRun()
452454
print("#\(config.delim)Test\(config.delim)[Tags]")
453455
for (index, t) in config.tests {
454456
let testDescription = [String(index), t.name, t.tags.sorted().description]
455457
.joined(separator: config.delim)
456458
print(testDescription)
457459
}
458460
case .run:
459-
config.findTestsToRun()
460-
printRunInfo(config)
461461
runBenchmarks(config)
462462
if let x = config.afterRunSleep {
463463
sleep(UInt32(x))

0 commit comments

Comments
 (0)