iOS の起動時間の最適化 - 関連#
背景#
iOS の起動時間の最適化に関する関連記事はたくさんありますが、自分で整理することでより深く理解できると思い、書くことにしました。ここでは、原理、実践、面接に関連する 3 つの側面からアプローチします。まず、アプリの起動原理と、起動時に開発者が最適化できるイベントについて理解する必要があります。次に、実際に試してみることで理解を深めます。最後に、起動の最適化に関連する面接について、いくつかの問題を挙げて説明します。
起動の原理#
起動には、コールドスタートとホットスタートの 2 つのタイプがあります。コールドスタートは、アプリのプロセスが終了し、ゼロから開始する場合を指します。ホットスタートは、アプリがバックグラウンドにある状態から前面に切り替わる場合を指します。通常、起動の最適化とは、コールドスタートの最適化を指します。(注:一部のバージョンでは、アプリを終了してすぐに再度開くとクラッシュする問題がありますが、これはシステムのバグです)。
コールドスタートのプロセスは、main
関数の前(pre-main)とmain
関数の後の 2 つの段階に分かれます。
pre-main 段階#
多くの記事で説明されているように:
pre-main 段階は、dylibs loading
→ rebase/binding
→ ObjC setup
→ initializer
の 4 つの部分に分かれます。それぞれの部分については省略しますが、この時点で尋ねられた場合、これらの 4 つのステップを暗記するだけで本当に疲れます😂。
なぜ困難に感じるのかというと、これらの 4 つのステップがどこから来たのかわからないからです。だから覚えるしかなく、私の記憶力は良くないので、「若くはない」ということになります。
だから、死に物狂いで覚えるだけでなく、実践して理解することができるのは何かということです。
それでは、実践と理解のためにやってみましょう:
まず、Xcode のスキームを開き、Run オプションの下にある「Environment Variables」を選択し、「DYLD_PRINT_STATISTICS」という名前を追加し、「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
がオンになっているためです。オフにするには、次のようにチェックを外します。
では、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 クラスの登録。
- カテゴリメソッドの挿入。
- 各セレクタが一意であることを保証する。
initializer time
:- C++ の静的オブジェクトの初期化。
- objc の
+load
メソッドの読み込み。 main()
の実行。
main 関数の後の段階#
main 関数の後の最適化も重要です。皆さんはapplication:didFinishLaunchingWithOptions:
が起動時に初期化されるメソッドであることを知っていますが、ここで何をすべきでしょうか?
まず、皆さんに質問です。
最適化の実践#
application:didFinishLaunchingWithOptions:
の中にreturn YES
の前にsleep(10)
を書いてみてください。このメソッドが返らない限り、画面にはLaunchScreen
が表示され、ホーム画面が初期化されているにもかかわらず表示されません。
面接に関連する質問#
+initialize、+init、+load はいつ呼び出されますか?呼び出される順序は?
+initialize、+load の違いは何ですか?
+load は main 関数の前にロードされますか?それとも後ですか?
参考#
Reducing Your App’s Launch Time
optimizing_app_startup_time
iOS 深思篇 | 启动时间的度量和优化