はじめに
Swiftで書いたコードの処理速度を測りたい時、オレオレベンチマークを使うより、Googleが開発しているswift-benchmarkのほうが正確に測ることができるかもね1。というわけで、その使い方を書いてみた記事。
swift-benchmarkの使い方
ここからはSwift Package Managerを利用してswift-benchmarkを使う方法を書いていくよ2。
新規にパッケージを作る
ターミナルでパッケージ用のディレクトリを作ろう。
そのディレクトリでパッケージを初期化しよう(--type=executable
を忘れずに)。
% mkdir use-swift-benchmark
% cd use-swift-benchmark
% swift package init --type=executable
Creating executable package: use-swift-benchmark
Creating Package.swift
Creating README.md
Creating .gitignore
Creating Sources/
Creating Sources/use-swift-benchmark/main.swift
Creating Tests/
Creating Tests/use-swift-benchmarkTests/
Creating Tests/use-swift-benchmarkTests/use_swift_benchmarkTests.swift
Package.swift
をイジろう
dependencies
にswift-benchmarkを追加しよう。
今回、テストは必要ないから.testTarget
は消しちゃおう(なんならTests
ディレクトリも消しちゃってOK)。
// swift-tools-version:5.3
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "use-swift-benchmark",
dependencies: [
// Dependencies declare other packages that this package depends on.
.package(name: "Benchmark", url: "https://github.com/google/swift-benchmark", from: "0.1.0"),
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages this package depends on.
.target(
name: "use-swift-benchmark",
dependencies: ["Benchmark"]),
]
)
main.swift
をイジろう
ターミナルにopen -a Xcode Package.swift
と打ち込もう("Package.swift"をFinderでダブルクリックするだけでいいけど)3。
そこで Sources
> use-swift-benchmark
> main.swift
を編集してみよう。
たとえば…
// https://github.com/google/swift-benchmark/blob/main/Sources/BenchmarkMinimalExample/main.swift をもとに少し改変
import Benchmark
let N = 10000
var stringWithNoCapacity: String = ""
var stringWithReservedCapacity: String = ""
benchmark("add string no capacity ") {
stringWithNoCapacity = ""
for _ in 1...N {
stringWithNoCapacity += "hi"
}
}
benchmark("add string reserved capacity") {
stringWithReservedCapacity = ""
stringWithReservedCapacity.reserveCapacity(N * 2)
for _ in 1...N {
stringWithReservedCapacity += "hi"
}
}
Benchmark.main()
guard stringWithNoCapacity == stringWithReservedCapacity else {
fatalError("Unexpected Result.")
}
早速、測ってみよう
% swift run
Error: Please build with optimizations enabled (`-c release` if using SwiftPM,
`-c opt` if using bazel, or `-O` if using swiftc directly). If you would really
like to run the benchmark without optimizations, pass the `--allow-debug-build`
flag.
ですよね。最適化を有効にした状態で測定するべきですよね。
というわけで…
% swift run -c release
running add string no capacity ... done! (2195.90 ms)
running add string reserved capacity... done! (2003.93 ms)
name time std iterations
----------------------------------------------------------------
add string no capacity 557263.000 ns ± 40.31 % 2292
add string reserved capacity 516282.000 ns ± 32.52 % 2295
できた!
おわりに
swift-benchmarkを使うことで、簡単にベンチマークを取ることができました。
もっといろいろな機能があるようですので、要チェックや(死語)。