性能测试 提供了用于检查算法和数据结构操作的渐近复杂度的工具。
例如,这对于确保您编写的、本应以恒定时间(即 O(1))执行的算法不会意外变成平方阶(即 O(n2))特别有用。
可以通过 Benchmark
结构上的静态方法测试三种类型的操作。
如果您正在测试的操作不会改变其对象(例如,Array.count
),请使用 Benchmark.nonMutating
。
let benchmark = Benchmark.nonMutating(setup: { Array(0..<$0 }) { _ = $0.count }
如果您正在测试的操作会改变其对象(例如,Set.insert
),请使用 Benchmark.mutating
。
let benchmark = Benchmark.mutating(setup: { Set(0..<$0) }) { _ = $0.insert(1) }
对于不作用于数据结构的算法(例如,fibonacci
等),Benchmark.algorithm
会消除 setup
阶段,并将大小直接转发到 measuring
闭包中。
let benchmark = Benchmark.algorithm { _ = fibonacci($0) }
我们相当肯定 Stdlib 文档中记录的性能保证是准确的,因此我们使用这些作为测试我们测试机制的用例。
例如,为了验证 Array
的 count
属性以恒定时间执行,可以在 XCTestCase
子类中执行以下操作。
func testArrayCountIsConstant() {
// Create a `Benchmark` for the given operation.
let benchmark = Benchmark.nonMutating(
// For each size, creates an `Array` with elements increasing from zero up to the size
setup: { size in Array(0 ..< size) },
// Measures `array.count` 10 times by default, averaging out the results
measuring: { array in _ = array.count }
)
XCTAssert(benchmark.performance(is: .constant))
}
通过使用尾随闭包语法和简写闭包参数名称,可以将以上内容缩短为:
let benchmark = Benchmark.nonMutating(setup: { Array(0..<$0) }) { _ = $0.count }
XCTAssert(benchmark.performance(is: .constant))
可以通过指定 trialCount
(即,每个测试大小执行操作的次数)和 testPoints
(即,执行操作的大小)来设置更多配置,如下所示:
let benchmark = Benchmark.nonMutating(
trialCount: 1_000,
testPoints: [1, 10, 100, 1_000, 1_000_000, 1_000_000_000],
setup: { size in Array(0 ..< size) },
measuring: { array in _ = array.count }
)
Scale
命名空间提供默认的 testPoints
(.tiny
, .small
, .medium
, .large
),这些对于大多数测试都适用。
有关更多使用示例,请参见 ./Tests
。
通过将以下行添加到您的 Package.swift
的 dependencies
部分来包含此软件包:
.package(url: "https://github.com/dn-m/PerformanceTesting", .branch("master"))
在您的测试文件的顶部添加 import PerformanceTesting
,就可以开始使用了。
使用以下命令克隆和构建此项目:
git clone https://github.com/dn-m/PerformanceTesting && cd PerformanceTesting
swift build
要运行库附带的测试:
swift test