Swift 4.1 のコードサイズ最適化モード


2018年2月8日 Erik Eckstein


Swift 4.1 では、コンパイラは新しい最適化モードをサポートしており、これにより専用の最適化を可能にし、コードサイズが削減されます。


Swift コンパイラには強力な最適化機能があります。-O を指定してコンパイルすると、コンパイラは最大のパフォーマンスで実行するようにコードを変換しようとします。しかし、この実行時パフォーマンスの向上は、時にコード・サイズの増加を伴うことがあります。新しい -Osize 最適化モードでは、ユーザーは最大速度ではなく最小限のコードサイズでコンパイルする選択ができます。


コマンドラインでサイズ最適化モードを有効にするには、-O の代わりに -Osize を使用して下さい。Xcode 9.3 には、新しい Swift コンパイラコード生成ビルド設定があります。


Xcode-Osize-setting


また、コンパイルモード (単一ファイルまたは全モジュール) を、最適化モードとは独立して選択できるようになりました。


Xcode-mode-setting


-Osize モードは、全モジュールモードと単一ファイルコンパイルモードで動作しますが、全モジュールモードで最適な最適化結果が得られます。


-Osize を使用すると、一部のプロジェクトでコードサイズが 5 %から 30 %に減少することがわかりました。


しかし、パフォーマンスはどうですか?これはプロジェクトに完全に依存します。大部分のアプリケーションでは、-Osize でヒットしたパフォーマンスは無視できます (すなわち 5 %未満)。しかし、パフォーマンスに敏感なコード -O はまだまだ良い選択かもしれません。


コード最適化への影響


コンパイラが -Osize を使った異なる点について詳しく説明しましょう。-Osize を指定すると、コンパイラは  -O と同様にコードを最適化します。しかし、-O とは対照的に、コンパイラはコードの重複を避けようとします。たとえば、関数をインライン化するべきか決定する場合、コンパイラは、サイズの下限を使用して関数をインライン化します。


関数のインライン化を完全に無効にするのは悪い考えです。なぜなら、小さな関数をインライン化するとコードサイズが改善されるからです。例えば以下のような単純なゲッタ関数を考えてみましょう。


struct X {
    var x: Int { return 27 }
}


このゲッタを呼び出すオーバーヘッドは、関数をインライン化するよりもはるかに高いでしょう。これは極端な例ですが、インライン展開はコードサイズを改善しながらも一定のサイズまで価値があることが判明しています。さらに、関数のインライン化によって他の最適化が引き起こされ、代わりにコードサイズが減少する可能性があります。たとえば、ゲッタの a.x をインライン展開する以下のコードスニペットでは、a.x27 と評価され、したがって if 分岐全体を最適化することができます。


func foo(a: X) {
    if a.x != 27 {
        // Can be optimized away if the getter of a.x is inlined
    }
}


インライン化のほかに、コンパイラは -Osize を使用して他のコードサイズに特化した最適化を実行します。たとえば、汎用型や Objective-C ブリッジ化を処理するいくつかのコードパターンは、ヘルパー関数に抽出され、インラインで生成されません。


結論


新しい -Osize 最適化モードは、すごいパフォーマンスには敏感ではないプログラムのコードサイズを減らすのに素晴らしい方法です。


-Osize を試して、フィードバックを是非お寄せください。osize タグを使用した、あなたの経験をフォーラムで共有してください。


<-Swift フォーラム開店! Swift 4.2 リリースの過程->






目次
Xcode 10 の新機能

SwiftLogo
  • Swift 4.2 全メニュー

  • Swift について

  • ブログ
  • Swift 4.1 のコードサイズ最適化モード
  • コード最適化への影響
    結論

  • Swift のダウンロード

  • Swift 入門

  • 文書化

  • ソースコード

  • コミュニティガイドライン

  • 投稿

  • Swift の継続的統合

  • Swift ソースの互換性

  • フォーカスエリア

  • ABI の安定性

  • サーバー API プロジェクト

  • コンパイラと標準ライブラリ

  • プロジェクト

  • パッケージマネージャ

  • Swift コアライブラリ

  • REPL とデバッガ、プレイグラウンド













  • トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)












    トップへ(Swift 4.2)