我怎么能运行我的性能测试超过十次?

How can I run my performance tests more than ten times?

默认情况下,Xcodes 性能测试是 运行 十次,我的结果是这十次测试的平均值。问题是每次 运行 平均结果都会有很大差异,所以我必须 运行 测试至少五次才能获得收敛结果。这既乏味又费时;有没有办法将 XCode 或单元测试本身配置为 运行 十次以上?

简答:不,目前没有暴露的接口允许一个measure block超过十次。

较长的答案:不,但是有一个接口公开来修改度量块的某些指标。默认指标位于从 defaultPerformanceMetrics 返回的字符串数组中。目前似乎只支持一种指标:XCTPerformanceMetric_WallClockTime。这仅指定了一个性能指标,该指标记录调用性能测试的 startMeasuring()stopMeasuring() 方法之间的时间(以秒为单位),而不是块 运行.[=15= 的次数]

XCTestCase 的 class 转储公开了此方法:

- (void)_recordValues:(id)arg1 forPerformanceMetricID:(id)arg2 name:(id)arg3 unitsOfMeasurement:(id)arg4 baselineName:(id)arg5 baselineAverage:(id)arg6 maxPercentRegression:(id)arg7 maxPercentRelativeStandardDeviation:(id)arg8 maxRegression:(id)arg9 maxStandardDeviation:(id)arg10 file:(id)arg11 line:(unsigned long long)arg12;

调配此方法时,第一个参数 (arg1) 具有 10 个持续时间:

["0.003544568",
"0.003456569",
"0.003198263",
"0.003257955",
"0.003508724",
"0.003454298",
"0.003461192",
"0.00423787",
"0.003359195",
"0.003335757"]

我在将其传递回原始实现之前在此列表的末尾添加了 4 个新值(1.0、2.0、3.0、4.0),但不幸的是观察到一个不同的 class,XCTestLog, 有一个内部完整性检查被触发:

Assertion failure in +[XCTestLog _messageForTest:didMeasureValues:forPerformanceMetricID:name:unitsOfMeasurement:baselineName:baselineAverage:maxPercentRegression:maxPercentRelativeStandardDeviation:maxRegression:maxStandardDeviation:file:line:]
caught "NSInternalInconsistencyException", "Performance Metrics must provide 10 measurements." 

一旦 XCTestLog 方法也被重写,因此它不会断言,可以添加额外的 4 个值而无需任何抱怨。不幸的是,该视图仍然只显示 10 个结果。

但是它确实更新了迷你视图中的总时间 + 标准差值。

调配前

Swizzling 并添加 4 个值后

为了查看超过 10 个结果,可能需要调整 XCode 运行时以告诉 table 显示更多项目。

我通常会扩展标准差值以包含我接受的范围。

一个明显的解决方法是在您正在执行的测量块内执行该操作 5 次。 (您需要更改预计时间。)

    measure {
        for _ in [1...5] {
            // ...
        }
    }

在最新的 Xcode (11.0+) 中,您不需要调配来更改迭代次数。使用以下 function:

func measure(options: XCTMeasureOptions, block: () -> Void)

这将允许您指定 XCTMeasureOptions 其中有 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.