swift-benchmarkを使ってみよう。

# はじめに

Swiftで書いたコードの処理速度を測りたい時、オレオレベンチマークを使うより、Googleが開発している[swift-benchmark](https://github.com/google/swift-benchmark)のほうが正確に測ることができるかもね[^swift-benchmark-version]。というわけで、その使い方を書いてみた記事。

[^swift-benchmark-version]: 記事執筆現在、最新バージョンは"0.1.0"です。即ち、開発段階にあることは留意が必要。


# swift-benchmarkの使い方

ここからは[Swift Package Manager](https://swift.org/package-manager/)を利用してswift-benchmarkを使う方法を書いていくよ[^end-of-words]。

[^end-of-words]: 記事によって語尾が安定しないのはご愛嬌…。

## 新規にパッケージを作る

ターミナルでパッケージ用のディレクトリを作ろう。  
そのディレクトリでパッケージを初期化しよう(`--type=executable`を忘れずに)。

```console
% 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:Package.swift
// 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でダブルクリックするだけでいいけど)[^package]。

[^package]: "Package.swift"ファイル単体の編集画面になっちゃった人は最新のXcodeを使おう。最新のXcodeなら"Package.swift"を開くだけで、パッケージ全体を編集できるウィンドウが開くよ。

そこで `Sources` > `use-swift-benchmark` > `main.swift` を編集してみよう。

たとえば…

```Swift: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.")
}


```


## 早速、測ってみよう

```console
% 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.
```

ですよね。最適化を有効にした状態で測定するべきですよね。  
というわけで…

```console
% 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を使うことで、簡単にベンチマークを取ることができました。
もっといろいろな機能があるようですので、要チェックや(死語)。