This is quite annoying.
Althought in Xcode 11, you can specify XCTMeasureOptions
when calling self.measure { }
, i.e., measure(options: XCTMeasureOptions, block: () -> Void)
. In the options
, you can set iterationCount
as 1.
BUT!
Setting iterationCount
as 1, Xcode will actually run the measure block twice, according to the doc of iterationCount
:
A performance test runs its block iterationCount+1 times, ignoring the first iteration and recording metrics for the remaining iterations. The test ignores the first iteration to reduce measurement variance associated with “warming up” caches and other first-run behavior.
And it did run twice in practice.
Meanwhile setting iterationCount
to 0 produces no result cause according to the doc:
... iterationCount+1 times, ignoring the first iteration and recording metrics for the remaining iterations
I don't know if the Runtime Swizzling way of changing the measurement count can get rid of the warm-up run though.
Workaround
Set up a counter to...
- skip the first run:
func testYourFunction() {
let option = XCTMeasureOptions()
option.iterationCount = 1
var count = 0
self.measure(options: option) {
if count == 0 {
count += 1
return
}
// Your test code...
}
}
- rollback the change:
func testYourFunction() {
let option = XCTMeasureOptions()
option.iterationCount = 1
var count = 0
self.measure(options: option) {
defer {
if count == 0 {
try? setUpWithError()
// call `setUpWithError` manually
// or run your custom rollback logic
}
count += 1
}
// Your test code...
}