この記事は Kateryna Semenova, Rahul Ravikumar, Chris Craik による Android Developers Blog の記事 " Improving App Performance with Baseline Profiles " を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。
多くのアプリにおいて、アプリのパフォーマンスとユーザー エンゲージメントとの間に相関性があることがわかっています。ユーザーが期待するのは、応答性が高く、読み込みが速いアプリです。起動時間は、アプリのパフォーマンスと品質の重要な指標の 1 つになっています。
私たちのパートナーのいくつかは、アプリの起動を最適化するために、すでに多くの時間とリソースを費やしています。その一例として、Facebook のストーリーをご確認ください。
この記事では、ベースライン プロファイルと、それがどのようにアプリやライブラリのパフォーマンスを改善するかを紹介します。その結果、起動時間が最大 40% 短縮されることもあります。ここでは起動に注目しますが、ベースライン プロファイルはジャンクにも大変有効です。
Android 9 (API レベル 28) では、アプリの起動時間短縮を目的として、Play Cloud に ART 最適化プロファイル (英語) が導入されました。クラウド プロファイルが利用できる場合、アプリのコールド スタートは、さまざまなデバイスで少なくとも平均 15% 高速になることがわかっています。
アプリがインストール後やアップデート後に初めて起動する場合、JIT コンパイルが行われるまでの間、コードはインタープリタ モードで動作します。APK では、Java と Kotlin のコードは dex バイトコードにコンパイルされますが、完全にコンパイルしたアプリの保存や読み込みにかかるコストの関係で、完全にマシンコードにコンパイルされることはありません (Android 6 以降)。アプリのクラスやメソッドのうち、頻繁に使われるものやアプリの起動に使われるものは、プロファイルのファイルに記録されます。そしてデバイスがアイドルモードになると、ART がそのプロファイルに基づいてアプリをコンパイルします。これにより、その後のアプリ起動が高速になります。
Android 9 (API レベル 28) より、Google Play もクラウド プロファイルを提供するようになっています。デバイスでアプリを実行すると、ART が生成したプロファイルが Play Store アプリにアップロードされ、クラウドに集約されます。アプリに対して十分な数のプロファイルがアップロードされると、Play アプリは集約したプロファイルを利用して、その後のインストールを行います。
クラウド プロファイルが利用できる場合、それが大きな効果を発揮してくれますが、アプリをインストールするときに常に利用できるとは限りません。通常、プロファイルの収集と集約には数日かかるため、多くのアプリで毎週アップデートが行われると、この点が問題になります。クラウド プロファイルが利用できるようになる前に、多くのユーザーがアップデートをインストールすることになるからです。そこで、Google の Android チームは、プロファイルが用意できるまでの時間を短縮する別の方法を探し始めました。
ベースライン プロファイルは、プロファイルを提供する新たなメカニズムであり、Android 7 (API レベル 24) 以降で利用できます。ベースライン プロファイルは、Android Gradle プラグインが生成する ART プロファイルです。人間が読むことができるプロファイル形式になっており、アプリやライブラリによって提供されます。たとえば、次のようなものです。
HSPLandroidx/compose/runtime/ComposerImpl;->updateValue(Ljava/lang/Object;)VHSPLandroidx/compose/runtime/ComposerImpl;->updatedNodeCount(I)IHLandroidx/compose/runtime/ComposerImpl;->validateNodeExpected()VPLandroidx/compose/runtime/CompositionImpl;->applyChanges()VHLandroidx/compose/runtime/ComposerKt;->findLocation(Ljava/util/List;I)I
HSPLandroidx/compose/runtime/ComposerImpl;->updateValue(Ljava/lang/Object;)V
HSPLandroidx/compose/runtime/ComposerImpl;->updatedNodeCount(I)I
HLandroidx/compose/runtime/ComposerImpl;->validateNodeExpected()V
PLandroidx/compose/runtime/CompositionImpl;->applyChanges()V
HLandroidx/compose/runtime/ComposerKt;->findLocation(Ljava/util/List;I)I
Compose ライブラリの例
バイナリのプロファイルは、APK のアセット ディレクトリの特定の場所 (assets/dexopt/baseline.prof )に格納されます。
ベースライン プロファイルは、ビルド時に作成され、APK の一部として Play に提供されます。そして、ユーザーがアプリをダウンロードするときに、Play からユーザーに送信されます。クラウド プロファイルがまだ利用できない場合、ベースライン プロファイルが ART クラウド プロファイル パイプラインの足りない部分を補います。クラウド プロファイルが利用できる場合、ベースライン プロファイルは自動的にクラウド プロファイルと結合されます。
ベースライン プロファイルの作成からエンドユーザーへの配信までのワークフローを示した図
ベースライン プロファイルの特に大きなメリットは、ローカルで開発や評価が行える点です。そのため、デベロッパーは実際にエンドユーザーが体験するパフォーマンスの向上を確認できます。また、クラウド プロファイルは Android 9 以降でしか利用できませんが、ベースライン プロファイルはそれよりも古いバージョンの Android (7 以降) でもサポートされています。
2021 年の前半に、Google マップのリリース サイクルが 2 週間から 1 週間に変更されました。アップデートの頻度が高くなるということは、ローカルの作成済みプロファイルがより頻繁に破棄され、Play クラウド プロファイルが存在しないために起動が遅くなるユーザーが増えるということでもあります。しかし、ベースライン プロファイルを使うことで、Google マップの起動時間は平均 30% 短縮され、それに伴って検索が 2.4% 増加しました。このように既に定着したアプリにとっても、非常に大きな成果です。
ライブラリに含まれるコードも、アプリのコードと同じです。デフォルトでは完全にコンパイルされないので、起動時のクリティカル パスで大量の処理を行う場合、問題につながる可能性があります。
Jetpack Compose は、Android システム イメージには含まれない UI ライブラリです。そのため、多くの Android View ツールキットのコードとは異なり、インストール時に完全にコンパイルされることはありません。そのため、パフォーマンスの問題が発生することがありました。特にそれが顕著だったのが、最初の数回のコールド スタート時です。
この問題を解決するため、Compose はプロファイル インストーラを利用します。これがベースライン プロファイルのルールを提供してくれるので、Compose アプリの起動時間やジャンクが減少します。
Google Play ストアの検索結果ページは、Compose を使って書き直されています。Compose からベースライン プロファイル ルールを取り込んだ後では、イメージを含む最初の検索結果ページを表示するまでの時間が最大 40% 短縮されました。
Android チームも、関連する AndroidX ライブラリにベースライン プロファイルを追加しました。これは、対象のライブラリを使うすべての Android アプリにメリットがあります。Constraint Layout では、プロファイルのルールを提供 (英語) することで、アニメーションのフレーム時間が 1 ミリ秒以上短縮されました。
ベースライン プロファイルを含めると、アプリやライブラリのデベロッパーすべてがメリットを得られます。理想的な方法は、特に重要なユーザー操作について、デベロッパーが複数のプロファイルを作成することです。それにより、クラウド プロファイルが利用できるかどうかによらず、常にその操作のパフォーマンスが高速になります。アプリ デベロッパーとライブラリ デベロッパー向けのベースライン プロファイルの設定方法は、詳細なガイドをご覧ください。
すぐにはアプリのベースライン プロファイルを作成できないという方でも、依存関係を更新することで、ベースライン プロファイルによるメリットを享受できます。Android Gradle Plugin 7.1.0-alpha05 以降でビルドすれば、ライブラリ (Jetpack など) が提供するベースライン プロファイルを APK に含めることができます。Google Play は、インストール時にそのプロファイルを使ってアプリをコンパイルします。プロファイルの追加は、アプリのビルドの一環として行うことができます。
忘れずに改善の測定を行うようにしましょう。生成されたプロファイルを使ってローカルで起動を測定するには、こちらの手順に従います。
ぜひフィードバックを共有し、皆さんの体験をお知らせください! (英語)