iOS 起動時間最適化 —— 関連#
背景#
iOS の起動時間最適化に関する記事はたくさんありますが、最初は書くつもりはありませんでした。しかし、自分で整理することで印象が深まると思います。ここでは原理 - 実践 - 面接関連の 3 つの側面からアプローチしようと思います。まずは APP 起動の原理を理解し、起動時に何が行われるのかを知る必要があります。そして、起動プロセス中のイベントの中で開発者が最適化できるものを実践します。最後に、面接関連について、起動最適化に関連する面接の質問をいくつか挙げたいと思います。
起動原理#
起動は冷起動と温起動に分かれます。冷起動は APP プロセスが終了した後、ゼロから開くことを指します。温起動は APP がバックグラウンドに入り、再びフォアグラウンドに切り替わるプロセスを指します。ここで通常言われる起動最適化は冷起動最適化を指します。(Ps: ここで特定のバージョンでは、終了した APP をすぐに再度開くと直接クラッシュする問題が発生することがありますが、これはシステムのバグです)。
冷起動のプロセスはmain関数の前(pre-main)
とmain関数の後
の 2 つの段階に分かれます。
pre-main 段階#
多くの記事が言うように:
pre-main 段階のプロセスはdylibs loading
——> rebase/binding
——> ObjC setup
——> initializer
の 4 つの部分に分かれます。それぞれの部分について... しかし、毎回この時に聞かれると、暗記するのは本当に疲れます😂。
なぜ難しいと感じるのでしょうか?それはこの 4 つのステップがどこから来たのかがわからないからです。だから暗記するしかありません。筆者は記憶力が悪く、結局「若くない」ので。
だから、暗記する以外に何ができるでしょうか?実践して理解することです。実際にやったことは印象に残ります。
では、どうやって実践 & 理解するか:
まず Xcode の Scheme を開き、Run のオプションの下でEnvironment Variables
を選択し、Name をDYLD_PRINT_STATISTICS
、Value を1
として追加します。以下のように:
その後、1 回実行すると、コンソールに以下のような情報が表示されます:
Total pre-main time: 599.52 milliseconds (100.0%)
dylib loading time: 101.25 milliseconds (16.8%)
rebase/binding time: 55.26 milliseconds (9.2%)
ObjC setup time: 189.95 milliseconds (31.6%)
initializer time: 253.04 milliseconds (42.2%)
slowest intializers :
libSystem.B.dylib : 6.65 milliseconds (1.1%)
libMainThreadChecker.dylib : 59.84 milliseconds (9.9%)
xxxTest : 313.12 milliseconds (52.2%)
ここにある情報を注意深く比較すると:Total pre-main time
はpre-main
の総時間を指します;
Total pre-main time
≈ dylib loading time
+ rebase/binding time
+ ObjC setup time
+ initializer time
;
slowest intializers
の中のlibMainThreadChecker
は、Scheme のMain Thread Checker
がオンになっているためです。オフにすれば大丈夫です。以下の場所のチェックを外せば OK です。
ではpre-main
段階で何が起こったのでしょうか?それはdylib loading
、rebase/binding
、ObjC setup time
、initializer time
が発生したということです。これでこの 4 つのステップの由来がわかりました。次に、これらのステップが何をしているのかを見てみましょう。
翻訳は以下の通りです:
Total pre-main time
はpre-main
の総時間を指します- すべての依存する動的ライブラリを読み込む;
DATA
内のポインタの偏差を修正する;- すべてのオブジェクトを初期化する。
dylib loading time
:- アプリが依存するライブラリを読み込む
- ライブラリが依存するライブラリを読み込む
rebase/binding time
:- rebasing: イメージのポインタを調整する
- binding: ポインタを外部イメージに設定する
ObjC setup time
:- objc クラスの登録 (class registration);
- Category メソッドの挿入;
- 各 Selector をユニークに保つ;
initializer time
:- C++ 静的オブジェクトの初期化
- objc の
+load
メソッドの読み込み main()
を実行する
main 関数の後の段階#
main 関数の後の最適化にも注意が必要です。皆さんも知っているようにapplication:didFinishLaunchingWithOptions:
は起動時に初期化するメソッドですが、ここでは何をすべきでしょうか?
まず皆さんに質問です。
起動最適化実践#
application:didFinishLaunchingWithOptions:
の中でreturn YES
の前にsleep(10)
を書いた場合、このメソッドが戻らない限り、画面にはLaunchScreen
が表示されます。たとえすでにホームページが初期化され、rootVC が設定されていても表示されません。
面接関連#
+initialize、+init、+load はいつ呼ばれ、呼ばれる順序は?
+initialize、+load の違いは?
+load の読み込みは main 関数の前ですか?それとも後ですか?
参考#
アプリの起動時間を短縮する
optimizing_app_startup_time
iOS 深思篇 | 起動時間の測定と最適化