Swiftのfor inとmapやreduceの速度を比べてみる

Ryoichi Izumita
3 min readFeb 1, 2018

--

先日Optional Bindingとnil比較の速度を比べてみましたが、

きしかわせんせいからfor inとmapなどを比べてみるというリクエストをいただいたので、早速やってみたいと思います。

ちなみにきしかわせんせい曰くSwift2や3ではfor inの方が速かったそうです。

今回の環境はSwift version 4.0.3とiPhone Xの組み合わせです。

for inとmapを比べてみます。

コードは以下のようになっています。testメソッドのクロージャ引数内の実行時間を出力します。Rangeから配列へ射影しますが、そのままコピーしているだけです。できるだけ簡素な実装にしています。

まずは-Ononeで最適化無しです。

Execution time - for in: 0.084015965461731
Execution time - map: 2.84733605384827

for inが圧倒的です。

次に-O -whole-module-optimizationで最適化します。

Execution time - for in: 0.0499699115753174
Execution time - map: 0.0190750360488892

mapの方が速くなりました。意外な結果です。Swiftのソースコードをみてみると(最新ではありますが)ContiguousArrayという型にキャパシティを設定して操作を行っています。ですので私のfor inソースコードでもキャパシティを設定してみます。するとmapと同程度の速度で実行されました。Arrayでも同様の結果でした。

最適化でmapメソッドがインライン化された(インライン化は-Ononeでも行われるように思いますので、whole module optimizationが影響しているのでしょうか。このあたり詳しい方が解説をお願いします。)のかmapメソッドの呼び出し時間が無くなり、純粋な実装の速度の差になっているようです。つまりfor inを使って射影を行うことはSwift開発者との技術比べということになるのかもしれません。分が悪いですね。

— -追記 — -

-Oのみにしても高速なのでwhole module optimizationは関係なさそうです。

次はfor inとreduceを比べてみます。reduceは高速だというintoの方です。

結果は

最適化無しでは大差がつきました。

Execution time - for in: 0.0403919219970703
Execution time - reduce: 3.41582703590393

しかし最適化を行うと

Execution time - for in: 0.0106049776077271
Execution time - reduce: 0.00971603393554688

mapと同様にreduceが高速化されました。速度的にはreduceとfor inはほぼ同じでした。Swiftのソースコードを読むとreduceの内部ではfor inを利用していました。

これら結果から、何らかの操作がメソッドで提供されている場合はそのメソッドを利用することで、Swiftの力やSwift開発者の技術力を有効に活用できるのではないかと思いました。for inを効率良く使うにはよりSwiftに精通する必要がありそうです。

--

--