【Android】起動時パフォーマンス改善のためにBaseline Profilesを導入したときのメモ


GoogleI/O 2022で話題にあがっていたBaselineProfilesを導入検討した際のメモを残しておきます。

# 背景

Baseline ProfilesはAPKに含まれるクラスとメソッドのリストです。インストール時に、Android Runtime(ART)によって、クリティカルなパスをプレコンパイルするために使用されます。
導入すると起動時間の短縮が期待できます。

> Baseline Profiles are a list of classes and methods included in an APK used by Android Runtime (ART) during installation to pre-compile critical paths to machine code. This is a form of profile guided optimization (PGO) that lets apps optimize startup, reduce jank, and improve performance for end users.

https://developer.android.com/topic/performance/baselineprofiles より


[GoogleMapでは30%起動時間が短縮された](https://android-developers.googleblog.com/2022/01/improving-app-performance-with-baseline.html)という話もありましたので、導入を検討してみました。

# 手順

- 依存の追加

```groovy:build.gradle:app
dependencies {
     implementation("androidx.profileinstaller:profileinstaller:1.2.0-beta01")
}
```

- rc-01 はCompileSdk32以上が要求されます。調子に乗ってWarningの言うままにバージョンを上げるとCompileSdkが31以下の場合エラーになります(なりました)
- macrobenchmarkのModule作成＆追加
    - https://developer.android.com/topic/performance/benchmarking/macrobenchmark-overview#setup-macrobenchmark
        - に従って行います。BunbleBee 以降であればポチポチで終わるので楽です。
- 追加で以下を対応します。

```diff:build.gradle:app
benchmark {
+    initWith buildTypes.release
    signingConfig signingConfigs.debug
    matchingFallbacks = ['release']
    debuggable false
+    proguardFiles "benchmark-rules.pro"
}
```
```text:benchmark-rules.pro(新規ファイル)
-dontobfuscate
```

- benchmarkのProductFlavorを追加(:appと同様にする。)
    - 定義だけあればOKです
    - 過不足があると`The consumer was configured to find a runtime of a component, as well as attribute 'com.android.build.api.attributes.BuildTypeAttr' with value 'benchmark', attribute 'com.android.build.api.attributes.AgpVersionAttr' with value '7.1.3'. However we cannot choose between the following variants of project :app:`みたいなエラーが出ます。
        
        ```groovy:build.gradle:benchmark
        flavorDimensions "default"
        productFlavors {
            develop {
            }
            staging {
            }
            productSub {
            }
            product {
            }
        }
        ```
        
- baseline profile file の取得
    - logcatに、以下のような感じでprofileの生成されたディレクトリが出力されます
        - `hoge.benchmark D/Benchmark: Usable output directory: /storage/emulated/0/Android/data/hoge.benchmark/cache`
    - ファイルをさがしてきてpullします
        ```
        $ adb shell
        # ls /storage/emulated/0/Android/data/hoge.benchmark/cache/
        
        $ adb pull /storage/emulated/0/Android/data/hoge.benchmark/cache/BaselineProfileGenerator_startup-baseline-prof-2022-06-23-05-38-13.txt
        ```
    - `baseline-prof.txt` にリネームして:appの`src/main` に配置します

# 効果計測
- [ドキュメントのサンプルコード](https://developer.android.com/topic/performance/baselineprofiles#measuring-optimization)をコピペでそのまま動きます。新しいテストを作成して上記をコピペしてきます。
- こちらは物理デバイスでないと動きません。
    - エミュレータで実行すると`java.lang.IllegalStateException:             Perfetto unexpected exit code, output = 19185
        EXITCODE=2` 的なエラーが出力されます。
- `hogebenchmark` のFlavorでビルドしたアプリを計測前にあらかじめインストールしておく必要があります。未インストールの場合、インストールされてますか的なエラーを出力してくれます。
- 実行すると、以下のような感じで結果を出力してくれます
 ![result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/418896/4913a0fd-8c1e-a5d7-8141-cde2ec621c92.png)


# まとめ

今回は期待したほどの効果はありませんでしたが大規模なアプリになるほど効果も大きくなるとドキュメントにもありますし導入もそれほど手間ではなかったので検討してみてもよいかと思いました。
また、実装の変更があるとProfilesを生成し直す必要がありますので効果がありそうならリリース前のCIにこれの自動生成を組み込むと良いと思います。
参考になりましたら幸いです。

参考

[https://developer.android.com/topic/performance/baselineprofiles#creating-profile-rules](https://developer.android.com/topic/performance/baselineprofiles#creating-profile-rules)
[https://speakerdeck.com/numeroanddev/improve-app-performance-with-baseline-profiles](https://speakerdeck.com/numeroanddev/improve-app-performance-with-baseline-profiles)
[https://github.com/STAR-ZERO/DagashiApp/pull/68/files](https://github.com/STAR-ZERO/DagashiApp/pull/68/files)
[https://github.com/android/nowinandroid/commit/5b54858642fff23ecd1eef3970e1f12e02167c5c](https://github.com/android/nowinandroid/commit/5b54858642fff23ecd1eef3970e1f12e02167c5c)
https://android-developers.googleblog.com/2022/01/improving-app-performance-with-baseline.html