Baidu APP iOS パッケージサイズ 50M の最適化実践 (7) コンパイラの最適化

I.はじめに

Baidu APP iOS パッケージ ボリュームの最適化シリーズの最初の 6 つの記事は、全体的なパッケージ ボリュームの最適化計画、イメージの最適化、リソースの最適化、コードの最適化、無駄なクラスの最適化、HEIC イメージの最適化の実践、および無駄なメソッドのクリーニングに焦点を当てています。徹底的な最適化は、アセット カタログと HEIC 形式の 3 つの観点から行われます。リソースの最適化には、大規模なリソースの最適化、無駄な構成ファイル、重複リソースの最適化が含まれます。コードの最適化には、無駄なクラスの最適化、無駄なモジュールのスリム化、無駄なメソッドのスリム化、重複コードの合理化、ツール クラスのスリム化、および AB の実験的な解決。この記事ではコンパイラの最適化に焦点を当てています。Baidu APP の実践では、コンパイラの最適化には、GCC 言語のコンパイルの最適化、Swift のコンパイルの最適化、LTO の最適化、デバッグ シンボルの削除、シンボル テーブルの削除、参照されていないコードの削除、資産の最適化、および C++ 仮想関数の最適化が含まれます。 -party SDK コンパイラの方向性をスリム化。さらに、命令セット アーキテクチャの最適化、XCode アップグレードの最適化、Swift 組み込みダイナミック ライブラリの最適化にも焦点を当てました。これら 3 つのモジュール最適化の基本原理はすべてコンパイラに関係するため、この章ではこれらをまとめて紹介します。

Baidu APP iOS パッケージのボリューム最適化実践シリーズの記事のレビュー:

1、 「Baidu APP iOS 端末パッケージ サイズ 50M の最適化実践 (1) 概要」

2、 「Baidu APP iOS 端末パッケージ サイズ 50M の最適化実践 (2) 画像の最適化」

3、 「Baidu APP iOS 端末パッケージ サイズ 50M の最適化実践 (3) リソースの最適化」

4、 「Baidu APP iOS 端末パッケージ サイズ 50M の最適化実践 (4) コードの最適化」

5、 「Baidu APP iOS 端末パッケージ サイズ 50M の最適化演習 (5) 役に立たないクラスの最適化と HEIC イメージの最適化演習」

6、 「Baidu APP iOS パッケージ サイズ 50M の最適化実践 (6) 無駄なメソッドのクリーニング」

2. コンパイラの最適化

2.1 プログラムの概要

写真

2.2 GCC 言語のコンパイルの最適化

2.2.1 概要

GCC のコンパイルと最適化を通じて、より小さなバイナリ製品が生成されます。これは、OC、C、および C++ に効果的です。

2.2.2 客観的な C++ コンパイルの最適化

Objective C++ の場合、XCode を使用して編集およびコンパイルします。コンパイル最適化構成パスは次のとおりです: ビルド設定 -> Apple Clang - コード生成 -> 最適化レベル。オプションのパラメーターは次のとおりです。

写真

写真

Xcode のデフォルトの最適化レベルは -Os ですが、ここでは -Oz 最適化メソッドを使用します。 WWDC 2019 の「Clang と LLVM の新機能」のリンク アドレス: https://developer.apple.com/videos/play/wwdc2019/409/ a>< a i=2> では、この最適化の原理が詳しく紹介されています。コンパイル単位内の関数間で同一のコード シーケンスを識別することにより、コード サイズを削減します。繰り返し連続する機械命令を関数に外部リンクし、元のコード列を外部接続関数に置き換えることで同じ機械語コードのスリム化を実現しますが、関数呼び出しスタックの深さが増すため、パフォーマンスへの一定の影響。時間が経ち、iPhone デバイスのハードウェア構成がますます高性能になるにつれて、このパフォーマンスの低下は許容範囲内になります。以下は、Oz 最適化の原理を説明するための公式デモの例です。 hasse 関数と kakutani 関数は同じ機械語命令を持ちますが、-Oz 最適化により OUTLINED_FUNCTION_O 関数が生成され、hasse 関数と kakutani 関数がこの関数を指すため、パッケージ サイズが削減されます。

写真

写真

公式の利点は 25% です。実際の効果から、コンパイル最適化パラメータ -Oz は、Objective C++ で書かれたコードに対して 10% のボリュームの利点があり、C&C++ に対して 30% のボリュームの利点があります。

2.2.3 C&C++ コンパイルの最適化

iOS 側では、ネットワーク ライブラリ、再生カーネル、ビジュアル処理、エンド インテリジェンスなど、多くの低レベル モジュールが C および C++ を使用して実装されています。同時に、これらのモジュールは Android や iOS などの複数のプラットフォームもサポートします。クロスプラットフォームを実現するために、これらのモジュールは通常、Cmake と GN という 2 つのコンパイル ツールを使用します。 Cmake は一般的なクロスプラットフォーム コンパイル ツールであり、その主な動作方法は、CMakeLists.txt ファイル内の指示を読み取って、対応するプロジェクト ファイルを生成することです。 GNコンパイルツールとはGenerate Ninjaの略で、Cmakeに代わるコンパイルツールです。 Google によってオープンソース化されており、C++ で書かれており、主にクロスコンパイルを実装し、出力プラットフォームのターゲットを指定できます。

CMake を使用するか GN を使用するかにかかわらず、コンパイラーの最適化構成は同じです。 C++ 言語の場合、cppFlags オプションは「-Oz」に設定され、C 言語の場合、cFlags オプションは「-Oz」に設定されます。

2.3 迅速なコンパイルの最適化

Swift コンパイルの最適化には、最適化レベルとコンパイル モードの 2 つのパラメーターがあり、構成パスは次のとおりです: ビルド設定 -> Swift コンパイラー - コード生成。

写真

最適化レベルのオプションのパラメーター値は次のとおりです。

写真

サイズの最適化の中心的な原則は、前に紹介した GCC 言語のコンパイル最適化における -Oz 最適化の原則と同じであり、どちらも、繰り返し連続するマシン命令をアウトライン化して再利用することで、コンパイルされた製品のサイズを削減します。ただし、この最適化方法はパフォーマンスにも一定の影響を与えますが、現在のハードウェア条件では、この影響は無視できます。

Compliation Mode のオプションのパラメータ値は次のとおりです。

写真

最適な結果を得るために、Optimize for Size[-Osize] と Whole Module が同時にオンになります。実際に実行すると、Swift パッケージのサイズが 10% 削減されることがわかります。

2.4 LTOの最適化

LTO (Link Time Optimization) は、Apple が正式に提案した最適化戦略です。公式説明によれば、LTOとはプログラムコード全体の最適化手法であり、LLVMコンパイラのリンクフェーズにおけるモジュール間の最適化である。この最適化により、コンパイラは一部の関数をインライン化し、呼び出されなかった冗長なコードを削除し、全体的な最適化を実行してプログラムの実行速度を向上させることができ、これらの最適化手段により、プログラムのコード サイズが効果的に削減され、プログラムの効率が向上します。

構成パスは次のとおりです: ビルド設定 -> Apple Clang - コード生成 -> リンク時間の最適化。設定値は増分です。最適化するには、メイン プロジェクトとフレームワークの両方でオンにする必要があります。

写真

LTO の最適化効果は、次の 3 つの側面に反映されます。

1. 関数のインライン化:

LTO では、一部の関数をインライン化できます。つまり、コンパイル時に関数呼び出しコードを呼び出しポイントに直接埋め込んで、関数呼び出しのオーバーヘッドを削減できます。これにより、プログラムの実行効率が向上します。

2. 不要なコードを削除します。

LTO は、未使用の変数、関数、クラスなど、プログラム内の不要なコードを特定して削除できます。これにより、生成されるバイナリ ファイルのサイズが小さくなり、プログラムの読み込みが速くなり、より効率的に実行できるようになります。

3. 全体的な最適化効果:

LTO はプログラムに対してグローバルな最適化を実行し、プログラム内で実行不可能なコード分岐を特定して最適化できます。たとえば、if ステートメントの特定の分岐が決して実行されない場合、LTO は生成されたバイナリ ファイルからその分岐を削除します。これにより、プログラムの実行効率とコードの品質が向上します。

LTO の悪影響には次のようなものがあります。

1. リンク マップの可読性を低下させます。

リンク マップは、リンカによって生成される、ターゲット ファイル間のリンク関係を記述するファイルです。 LTO を使用する場合、グローバル最適化により、生成されたリンク マップ内のクラス名が 0.arm64.thinlto.o などの数字で始まる場合があり、これによりリンク マップが大幅に読みにくくなります。リンク マップを読み取る必要がある場合は、まず LTO を閉じる必要があります。

2. コンパイルとリンクの時間を増やします。

LTO を有効にすると、コンパイルとリンクのプロセスに時間がかかります。これは、リンク フェーズ中に LTO が多数のグローバル最適化を実行し、より多くのコンピューティング リソースと時間を必要とするためです。オンライン パッケージ化またはオフライン コンパイルの場合、これにより時間がかかります。

2.5 デバッグシンボルの除去

写真

Symbols Hidden by Default は、シンボルのデフォルトの可視性を設定するために使用されます。YES に設定すると、XCode はすべてのシンボルを "private extern" として定義し、パッケージ サイズがわずかに小さくなります。ダイナミック ライブラリが NO に設定されている場合、リンク エラーが発生します。

2.6 ストリップシンボルテーブル

構成パスは「ビルド設定 -> リンクされた製品の除去」で、選択された属性値は YES です。

写真

リンクされた製品を削除して不要なシンボル情報を削除します。シンボル情報を削除した後は、シンボル化に dSYM ファイルのみを使用できるため、「デバッグ情報形式」を「DWARF with dSYM ファイル」に変更する必要があります。

写真

コピー中にデバッグ シンボルを除去する原理は、リンク製品を除去する原理と似ており、主に、プロジェクトにコピーされたサードパーティ ライブラリのシンボル テーブルを削除します。リリース モードでは「YES」、デバッグ モードでは「NO」に設定するだけです。そうしないと、シンボリック ブレークポイントを使用してサードパーティ ライブラリをデバッグできません。

写真

2.7 参照されていないコードを削除する

構成パスは「ビルド設定 -> デッド コード ストリッピング」で、選択された属性値は YES です。

写真

この最適化は主にリンク時にC、C++、Swiftなどの静的言語の無駄なコードをインストールパッケージから削除するものですが、Objective-Cは動的言語でありコンパイルされるため、Objective-Cの処理時には効果がありません。実行時メカニズムに基づいています。静的コンパイルは役に立たないと判断されます。コードは実行時に使用される可能性があります。

2.8 資産の最適化

アセット コンパイルの最適化構成パスは、[ビルド設定] -> [アセット カタログ コンパイラー] -> [最適化] です。

写真

最適化のオプションのパラメーター値は次のとおりです。

写真

「スペース」を選択すると、パッケージ サイズをある程度最適化できますが、メリットはわずかです。

2.9 C++ は仮想関数の使用を削減します

仮想関数の使用を減らすと、実際に仮想関数テーブルが占有するスペースが削減され、それによってパッケージのサイズが削減されます。仮想関数テーブルは、動的バインディングを実装するために使用されるデータ構造であり、クラスの仮想関数へのポインタを格納します。したがって、仮想関数の使用を減らすと、これらのポインターの数が減り、それによって仮想関数テーブルのサイズが削減され、最終的にはパッケージのサイズが削減されます。

2.10 サードパーティ製 SDK コンパイラのスリム化

コンパイラの設定方法とその最適化原理については上で詳しく紹介しましたが、メイン プロジェクトの最適化設定を変更するだけでは最良の結果を達成するのに十分ではありません。最良の最適化効果を達成するには、上記の構成に従って各フレームワークを調整する必要があります。これは、必要な特定の最適化効果を実現するには、各フレームワークのビルド構成で最適化を有効にし、コンパイラー パラメーターを適切な値に設定する必要があることを意味します。同時に、各フレームワークで使用されるライブラリと依存関係も正しく構成されていて、コンパイラの最適化で適切に動作することを確認する必要もあります。要約すると、コンパイラの最適化を実際に機能させるには、必要に応じて各フレームワークを構成し、微調整する必要があります。

Baidu APP は、主力アプリケーションとして、Baidu Maps、Baidu Netdisk、Du Xiaoman などの多くのサードパーティ SDK を統合しています。したがって、これらのサードパーティ SDK ビジネス パーティは、アプリケーションのスリム化を達成するためにコンパイラを最適化するよう促す必要があります。これらの最適化には、画像の最適化、リソースの最適化、コードの最適化などが含まれますが、これらに限定されません。これらの最適化手段により、アプリケーションのサイズが効果的に削減され、パフォーマンスが向上し、ユーザー エクスペリエンスが向上します。

3. 命令セットアーキテクチャの最適化

3.1 iPhoneの共通命令セットアーキテクチャ

iPhone フォンはすべて、低電力の arm プロセッサを使用しています。arm 命令セット アーキテクチャは、armv6、armv7、armv7s、および arm64 の 4 つのタイプに分かれています。それらは下位互換性を維持しています。たとえば、デバイス iphone13 は arm64 をサポートしていますが、armv7 もサポートしていますが、 armv7 iPhone 13 デバイスの優れたハードウェア特性を活用できません。シミュレータは arm 命令セットを実行できません x86 命令セットを実行します 32 ビット プロセッサは I386 命令セットをサポートします 64 ビット シミュレータは x86_64 アーキテクチャをサポートします さまざまなデバイスがサポートする命令セット アーキテクチャは次のとおりです

写真

ハードウェア デバイスが更新され続けるにつれて、初期のデバイス (iPhone4、iPhone5、iPad など) の市場シェアは重要ではなくなりました。したがって、モバイル デバイスの場合は、arm64 アーキテクチャのみをサポートする必要があります。同様に、シミュレータについても x86_64 アーキテクチャのみをサポートする必要があり、パッケージ ボリュームの最適化の観点から、現時点では各ライブラリは arm64 および x86_64 アーキテクチャのみをサポートする必要があり、他のアーキテクチャをサポートする必要はありません。

命令セット アーキテクチャを最適化すると、AppStore にアップロードされるパッケージのサイズを削減できますが、ユーザーがダウンロードするパッケージのサイズには最適化効果がありません。これは、Apple の App Thinning メカニズムでは、さまざまなデバイス モデルのハードウェア アーキテクチャに基づいてさまざまなコンパイル済み製品が生成されるため、さまざまなデバイスのユーザーが AppStore からダウンロードするパッケージも異なるためです。

3.2 命令セットアーキテクチャの設定

  • [アーキテクチャ] オプション、[ビルド設定] -> [アーキテクチャ] の値は、標準アーキテクチャ - $(ARCHS_STANDARD) で、実マシンでコンパイルした場合は実際には (armv7 および arm64)、シミュレータでコンパイルした場合は (x86_64、i386、arm64) になります。

  • [アクティブなアーキテクチャのみをビルド] オプション、[ビルド設定] -> [アクティブなアーキテクチャのみをビルド] の値が [はい] の場合、現在のアーキテクチャのみがコンパイルされることを意味します。通常、実マシンは arm64 で、シミュレータは x86_64 です。[いいえ] の場合は、現在のアーキテクチャのみがコンパイルされます。 、つまり、最初にサポートされているアーキテクチャを同時にコンパイルします。

  • [除外するアーキテクチャ] オプション、[ビルド設定] -> [除外するアーキテクチャ] の値は、除外するアーキテクチャです。たとえば、arm64 に設定されている場合は、製品に arm64 アーキテクチャが存在しないことを意味します。

写真

3.3 無駄なアーキテクチャを削除する

lipo コマンドを使用して、指定されたアーキテクチャ バイナリ ファイルを古いフレームワークの mach-o ファイルから分割し、それをマージし、最後に古いフレームワークの mach-o ファイルをマージされたバイナリ ファイルに置き換えます。

  • 以下に示すように、lipo -info コマンドを使用して、フレームワークに含まれる命令セット アーキテクチャ情報を表示します。AbcSDK.framework でサポートされる命令セットは、x86_64、i386、arm64、および armv7 です。
 lipo -info AbcSDK.framework/AbcSDK Architectures in the fat file: AbcSDK.framework/AbcSDK are: x86_64 i386 arm64 armv7

  • Lipo コマンドは、以下に示すように、指定されたアーキテクチャを抽出します。arm64 アーキテクチャは、AbcSDK.framework から抽出され、AbcArm64 に配置されます。x86_64 アーキテクチャは、抽出され、AbcArmX86_64 に配置されます。
lipo AbcSDK.framework/AbcSDK -thin arm64 -output AbcArm64lipo AbcSDK.framework/AbcSDK -thin x86_64 -output AbcArmX86_64

AbcArm64 および AbcArmX86_64 のアーキテクチャ情報を確認する

lipo -info AbcArm64Non-fat file: AbcArm64 is architecture: arm64lipo -info AbcArmX86_64Non-fat file: AbcArmX86_64 is architecture: x86_64

  • Lipo コマンドはアーキテクチャをマージし、AbcArm64 と AbcArmX86_64 をマージし、新しい newAbc を生成します。予想どおり、newAbc には x86_64 と arm64 の 2 つのアーキテクチャがあります。確認するには、lipo -info コマンドを使用します。
// 合成x86_64和arm64lipo -create AbcArm64 AbcArmX86_64 -output newAbclipo -info newAbcArchitectures in the fat file: newAbc are: x86_64 arm64
  • 元のバイナリ ファイルを置き換える 上記の操作の後、x86_64、i386、arm64、および armv7 の 4 つの命令セット アーキテクチャを備えた AbcSDK.framework は、x86_64 と arm64 の 2 つの命令セットのみをサポートするコンポーネントにスリム化されます。
mv -f newAbc AbcSDK.framework/AbcSDK

4. XCodeのアップグレードと最適化

Apple は開発者の生産性の向上に常に注力しており、毎年 XCode の新バージョンをリリースし、多くの最適化を行っています。また、パッケージの量に関しても積極的な措置を講じています。たとえば、10 月 22 日にリリースされた Xcode 14 には、新しい機能強化が加えられただけでなく、より強力な並列コンパイル機能も追加され、プロジェクトの構築速度が大幅に向上します。同時に、パッケージ容積の最適化も明らかです。

Xcode 14 でパッケージ サイズを最適化する具体的な技術ポイントを見つけるために、WWCD 情報をたくさん読みました。最終的に公式ドキュメント「アプリのサイズとランタイム パフォーマンスの向上」で答えを見つけました。リンク アドレスは次のとおりです。 https://developer.apple.com/videos/play/wwdc2022/110363/#, Xcode 14 では、次の 3 つの側面からパッケージ サイズが最適化されました。 :

  • メッセージ送信関数呼び出しの使用量が 12 バイトから 8 バイトに削減されました。

  • 関数呼び出しの保持と解放の使用量が 8 バイトから 4 バイトに減少しました。

  • 自動リリースの最適化、自動リリース省略の mov 命令を削除し、サイズを 4 バイト削減します。

5. 迅速な組み込み動的ライブラリの最適化

2014 年の WWDC でのリリース以来、Swift 言語は Apple の主導により大幅な発展を遂げてきました。その利点は iOS 開発の開発トレンドを表しており、使用量が増え続けるにつれて、Swift は最終的に Objective-C に代わって iOS 開発で優先される言語になると予想されています。現在、Swiftは大手企業やアプリケーションにとって必須の開発言語となっており、デイリーアクティブユーザー数トップ20の国内アプリのうち、Pinduoduoを除くすべての企業が開発にSwiftを採用しています。

ただし、Swift 言語で開発を開始するとすぐに、Swift システム ライブラリが iPA パッケージに追加されていることがわかります。これは、iOS12.2 より前のシステムには組み込みの Swift システム ライブラリがないため、iPA パッケージをパッケージ化して生成するときに XCode に Swift ライブラリが含まれるためです。次の Swift システム ライブラリは、 iPAパッケージ。

写真

さらに、APP に付属する WatchApp も Swift 言語を使用する場合、Watch のダイナミック ライブラリに Swift システム ライブラリが存在するため、iPA パッケージには 2 つの組み込みライブラリが含まれることになります。

最適化方法は非常に簡単で、APP がサポートする最小バージョンを 12.2 に変更するだけです。システム 12.2 以降には Swift システム ライブラリが付属しているため、それを APP に組み込む必要はありません。 Baidu APP パッケージ サイズの最適化を実践したところ、最適化後、iPA パッケージ サイズが 3,000 万以上削減され、3,000 万のダイナミック ライブラリが iPA パッケージに存在しなくなったことがわかりました。AppStore に送信した後、バックグラウンドを接続すると、次の利点があります。

  • iPhoneX、iPhone8、iPhone7 などの iPhoneX 以下のモデルの場合、インストール パッケージのサイズは 20M 減少し、ダウンロード パッケージのサイズは 10M 減少します。

  • iPhone以上の機種

Baidu APP の場合、iPhoneX 以下のモデルが占める割合は 5% 未満ですが、APP がサポートする最小バージョン番号を増やすと、一部のユーザーが失われることになります。これら 2 つの要素を考慮して、Swift の組み込み動的ライブラリの最適化ソリューションを使用しないことにしました。

6. まとめ

コードの最適化、リソースの最適化、イメージの最適化と比較して、コンパイラの最適化は、パッケージ ボリュームの最適化において最も高い投資収益率 (ROI) を実現します。ただし、各ライブラリのコンパイラ構成の変更はそのライブラリのすべてのコードに影響するため、コンパイラの最適化も最も大きな影響を及ぼします。したがって、最適化の品質は厳密に管理される必要があります。 Baidu APP の最適化実践中に、コンパイラ方向の最適化によりパッケージ サイズを 30M 削減することに成功し、独自のライブラリのすべての利点を実現しました。さらに、ボリュームでランク付けされた上位 15 のサードパーティ SDK もこの利点を達成しました。

この記事では、GCC 言語コンパイルの最適化、Swift コンパイルの最適化、LTO 最適化、デバッグ シンボルの削除、シンボル テーブルの削除、未参照コードの削除、アセットの最適化、C++ 仮想関数の最適化、サードパーティ SDK のコンパイルなど、Baidu APP のコンパイラ最適化ソリューションを体系的に紹介します。デバイス方向の重量減少など。さらに、命令セット アーキテクチャの最適化、XCode アップグレードの最適化、Swift 組み込みダイナミック ライブラリの最適化など、その他の最適化ソリューションも紹介されています。今後、他の最適化についてもその原理と実装について詳しく紹介していきますので、ご期待ください。

- 終わり -

参考文献:

[1]gcc コンパイラ設定:https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html

[2]LTO の使用方法:https://llvm.org/docs/LinkTimeOptimization.html

[3]XCode :https://developer.apple.com/library/archive/documentation/DeveloperTools/Reference/XcodeBuildSettingRef/1-Build_Setting_Reference/build_setting_ref.html#/ /apple_ref/doc/uid/TP40003931-CH3-SW102

[4] Clang と LLVM の新機能:https://developer.apple.com/videos/play/wwdc2019/409/

[5]XCode14 介绍:https://developer.apple.com/documentation/xcode-release-notes/xcode-14-release-notes

[6]アプリのサイズと実行時のパフォーマンスを向上させる:https://developer.apple.com/videos/play/wwdc2022/110363/#

推奨読書:

Baidu 検索コンテンツ HTAP テーブル ストレージ システム

ビッグモデルの時代、「誰でもAIができる」Baidu開発者プラットフォームとはどのようなものでしょうか?

数十万の QPS、Baidu のホット イベント検索の安定性保証の実践

Baidu検索の兆規模特徴量計算システムの実践

Python スクリプトによる OC コード再構築の実践をサポート (3): データ パスにアクセスするためのデータ項目使用モジュールの適応

SenseTime 創設者、Tang Xiaoou 氏が 55 歳で死去 2023 年、PHP は停滞 Wi-Fi 7 が完全に利用可能になる2024 年初頭にデビュー、Wi-Fi 6 の 5 倍高速 Hongmeng システムが独立しつつあり、多くの大学が「Hongmeng クラス」を設立 Zhihui Jun の新興企業が借り換え、金額は 6 億元を超え、事前評価額は 35 億元 Quark Browser PC 版が内部テストを開始 AI コード アシスタントは人気があり、プログラミング言語のランキングはすべてです できることは何もありません Mate 60 Pro の 5G モデムと無線周波数技術ははるかに先を行っています MariaDB が SkySQL を分割し、確立されました独立した企業として<​​/span> Xiaomi、Yu Chengdong 氏の Huawei からの「キールピボット」盗作声明に対応
{{名前}}
{{名前}}

おすすめ

転載: my.oschina.net/u/4939618/blog/10319259