簡易なSwiftパフォーマンス測定クラスを作った
Table of Contents
普段からSwift言語でコーディングしても、Swift内部の動きが分からず書き方の違いでパフォーマンスが変わります。
Swift自体のコードを読めば理解できるかもしれません。しかしコンパイラコードを読むのはかなりの労力を時間を必要とします。目的が「どっちの書き方が速いか?」だけであればコスパ悪いです。
この記事では、速度パフォーマンスのコード検証におけるボイラープレートコードの説明と、それを軽減するために私が作成したクラスを紹介する記事です。
速度パフォーマンス測定の仕組み
速度パフォーマンスを検証するなら大抵は次の工程になります。
- Playgroundや簡単なXcodeプロジェクトを用意
- 検証コードを実装
- 検証コード前後に開始と終了の差分時間を確保
- 複数回実行して差分時間を集める
- 差分時間の最速/最遅を除去
- 差分時間の最速/最速/平均を算出する
複数回実行する理由
1回の測定では測定誤差の解消ができません。
なので通常は複数回コードの検証を実施結果の平均値などを使います。
最速と最遅を除去する理由
測定誤差の影響を強く受けた最速と最遅をなくすためです。
Swiftのコード検証はコスパ悪い
速度パフォーマンスの仕組みは単純です。しかし目的に対する労力が見合ってません。
簡単なコード検証をしたいだけなのに、測定の仕組みを用意するのは面倒です。
仕組みは単純でも、検証のたびに必要になるし、検証コードよりも測定コードが長いことも…
コード検証はフットワークが重要
ふと思いついたこと、どっちがいいのかモヤモヤしてるときに「ササッ」と調べたいですよね。
頭の中に検証コードは入ってるのに、それ以上に検証に時間がかかるのはストレスです。
毎度その状態だと、次第に検証を諦めてしまいます。
コード検証は、結果と同じぐらい速度が重要です。
速度パフォーマンス測定クラスの作成
検証コードの実装や結果を得る作業が正味作業だとすれば、測定の仕組みを実装するのは付帯作業です。
そして毎回同じ測定の仕組みを実装するのは無駄作業です。
なので検証コードに注力できるように、速度パフォーマンス測定において最低限の機能をもつクラスを作成しました。
主に自分向け
主に自分用に用意しました。
ローカルにこのファイルを置いてても場所を忘れたりPCリプレイスやPC故障でロストを考えてGitHubに上げました。
とはいえ内容はシンプルでユースケースも明確なので使いたい方は使っていただいても構いません。
手軽さ重視
パフォーマンス測定時の環境を考えて、libかframeworkにせず、CocoaPodsやCarthageにも対応しません。
単純にファイル単体を落として参照して使うだけです。
コード検証時にはそれぐらい単純な方がコスパがよいためです。
仕組みについて
仕組みは、検証回数と検証コードをクロージャで渡せば、戻り値で検証結果を得られます。
検証結果には、検証名、最速時間、最遅時間、平均時間の情報を保持しています。
また最速と最遅は除外してるため検証回数-2が検証結果数になります。
検証作業はスペシャリストへの階段
- どっちの書き方がいいのか?
- この処理って実は重いのか?
- どう書けば速いのか?
などは、実はCPUやレジストリ、キャッシュ、メインメモリ、仮想メモリ等ハードウェアに依存していたり、言語自体の実装に依存することが多いです。
C/C++では、vtableやオーバーヘッドなど言語自体の要因もありますが、ハードウェアよりの依存が比率的に高くなります。
一方SwiftはCやアセンブラと異なり直接メモリ操作を指示するコードはほぼほぼ使いません。
そのため、「どの書き方がメモリに親切なのか」「無駄な処理が走らないか」などはSwift言語自体のコードを読まないとわかりません。しかし測定することでそれを結果として知ることはできます。
Swiftは主にiOSで使われる言語で主に高レイヤーな領域のコーディングで使われることが多いですが、 新しいデータ構造を自作したりキャッシュ機構を自作したりなど少し低レイヤーな領域のコーディングするときに、どの書き方なら安定して速度を出せるのか?を知っているだけコードのパフォーマンスは変わります。
速く書けるだけがスペシャリストではありません。
速く動くコードを書けるのもスペシャリストとして大事なことです。
そのために検証作業は大事な手段となり、今回用意したコードは検証速度を円滑にするツールとなります。