R8 構成アナライザを使用する

R8 構成アナライザは、アプリの構成品質に関する詳細な分析情報を提供することで、R8 のパフォーマンス上のメリットを最大限に高めることを目的としたツールです。この機能を使用すると、最適化可能なコードベースの割合を示す主要な指標(圧縮スコア、最適化スコア、難読化スコア)をモニタリングして、R8 の最適化を追跡し、改善できます。アナライザは、サードパーティ製ライブラリによって導入されたものも含め、広範または不要なキープルールを特定することで、R8 ができるだけ多くのクラス、フィールド、メソッドを効果的に最適化できるように、構成を調整するのに役立ちます。

レポートを生成する

AGP 9.3.0-alpha05 以降では、R8 ビルドを実行すると、レポートが build/outputs/mapping/release/configanalyzer.html に自動的に生成されます。出力の自動生成を無効にするには、次の Gradle プロパティを設定します。

android.experimental.r8.enableR8ConfigurationAnalyzer=false

AGP 9.2 以前の場合、R8 でビルドが有効になっている Gradle タスクを実行するときに、com.android.tools.r8.dumpkeepradiushtmltodirectory システム プロパティを設定します。

./gradlew assembleRelease \
    -Dcom.android.tools.r8.dumpkeepradiushtmltodirectory=<output_directory>

たとえば、次のコマンドを使用して、/tmp/r8analysis ディレクトリに HTML レポートを生成します。

// To create the /tmp/r8analysis folder.
mkdir -p /tmp/r8analysis

// To generate the report in the /tmp/r8analysis folder.
./gradlew assembleRelease \
    -Dcom.android.tools.r8.dumpkeepradiushtmltodirectory=/tmp/r8analysis

レポートを理解する

R8 構成アナライザは、アプリの R8 構成と、各保持ルールのアプリへの影響に関する分析情報を提供します。これにより、R8 から最大限の最適化を実現し、アプリのパフォーマンスを向上させることができます。次のスコアを使用して、コードベースのどの程度を R8 で最適化できるかを確認します。

レポートの概要セクションの例
図 1. レポートの概要セクションの例。

スコアの縮小

R8 はアプリを圧縮する際、使用されていないコードとリソースを特定して削除することで、アプリの全体的なサイズを縮小し、最終ビルドをできるだけ小さくします。縮小スコアは、縮小の対象となるクラス、フィールド、メソッドの割合を追跡します。たとえば、縮小スコアが 66% の場合、R8 はコードベースの 66% で縮小を実行できます。

最適化スコア

R8 は、メソッドのインライン化やクラスの統合などの最適化を実行し、アプリの起動とメモリを改善します。最適化スコアは、R8 の最適化の対象となるクラス、フィールド、メソッドの割合を追跡します。たとえば、最適化スコアが 66% の場合、R8 はコードベースの 66% でしか最適化を実行できないことを意味します。

難読化スコア

R8 は、クラス、フィールド、メソッドを短い名前に難読化することで、アプリのメタデータ フットプリントを削減し、メモリを節約します。難読化スコアは、コードベース内で難読化可能なコードの割合を測定します。

保持ルールの調整

スコアを改善し、R8 の最適化をより効果的に行うには、R8 がアプリを不必要に最適化しないように、キープルールを調整する必要があります。リフレクションを使用してアクセスされるクラス、メソッド、フィールドのみを保持する必要があります。

これを行うには、保持ルール分析を使用します。

保持ルールの分析の例
図 2. 保持ルールの分析の例。

ルールの詳細な分析を表示するには、ルールをクリックして詳細画面を開きます。

保持ルールの分析の例
図 3. 保持ルールの分析の例。

保持ルールの絞り込み方法

キープルールを調整し、アプリの R8 最適化の可能性を最大限に引き出すには、次の操作を行います。

  1. Configuration Analyzer で、各保持ルールについて、R8 で最適化できないクラス、フィールド、メソッドの割合を確認します。このオプションは、多数のクラス、フィールド、メソッドで最適化を妨げている保持ルールを特定するために使用します。各保持ルールによって防止される最適化プロパティも一覧表示されます。
  2. 多数のクラスの最適化を妨げている保持ルールがある場合は、その保持ルールによって最適化が妨げられているクラス、フィールド、メソッドを確認し、リフレクションを使用して動的に呼び出されないアイテムがそのルールによって保持されているかどうかを確認する必要があります。
  3. 適切な保持オプションを選択し、ベスト プラクティスに従うことで、必要なクラス、フィールド、メソッドのみをターゲットにして、保持ルールによってブロックされる最適化を減らします。
  4. 影響を受けるクラス、フィールド、メソッドをカバーするテストを調査して実行し、キープルールを調整します。

ライブラリの最適化を検査する

サードパーティのライブラリを統合すると、多くの場合、R8 と連携するための独自のコンシューマー キープルールが含まれます。ライブラリの作成者は特定の実装を予測できないため、必要以上に多くのクラス、フィールド、メソッドで最適化を妨げるような、広範囲に及ぶ保守的なルールを記述することがあります。これにより、ライブラリの実際のランタイム実行とは関係のないアプリの部分が R8 によって最適化されない可能性があります。R8 構成アナライザを使用すると、アプリの最適化に悪影響を及ぼすルールを導入しているライブラリを特定できます。

構成アナライザを使用して、統合されたすべてのコンシューマー keep ルールの複合効果を検査します。サードパーティ ライブラリから取得した各キープルールの影響を分析することで、アプリの最適化を大幅に妨げている特定のサードパーティ ライブラリを特定して追跡できます。

ライブラリを最適化する方法

  • ライブラリに広すぎるルールが含まれている場合は、レポートのデータを使用して、現在のルールがアプリの最適化スコアにどのように影響するかをライブラリのメンテナーに説明することをおすすめします。外部ライブラリの場合は、問題を報告する前に、ライブラリ内の既存のバグを探してください。
  • 必要に応じて、特定のライブラリのルールを除外することで、改善の可能性をテストできます。ライブラリのルールをプロジェクトにインポートし、広範なルールを除外して、構成アナライザを再実行し、サイズとパフォーマンスの潜在的な改善を測定できます。

包含されたルール

複数の保持ルールが重複している場合、いずれかのルールが不要な最適化を妨げている可能性があります。コードベースに 2 つの keep ルールがある場合。

# Prevents optimization in the entire package
# Remove this to improve optimization
-keep class com.example.package.** { *; }

# Prevents optimization to the class inside the package
-keep class com.example.package.Myclass

パッケージ全体の最適化を防止する最初の保持ルールが、最初の保持ルールによって保持されるパッケージ内のクラスをターゲットとする 2 番目の保持ルールを包含しています。keep ルールが重複している場合、必要以上に最適化がブロックされることがあります。重複するルールを絞り込むことで、R8 の最適化を最大限に高め、技術的負債を解消できます。このプロセスでは、構成を合理化して、R8 の最適化機能を最大限に活用しながら、不可欠なコードのみを保持します。

レポートの概要セクションの例
図 4. レポートのサブサンプション ルールの例。

包含されたルールを最適化する

  1. R8 構成アナライザを使用して、包含する keep ルールを見つけます。
  2. コードベース内でリフレクションに依存しているクラス、フィールド、メソッドを特定します。これらは、キープルールを使用して保持する必要があります。この情報を把握することで、保持ルールの調整に役立ちます。
  3. 構成アナライザを使用して、同じクラス、フィールド、メソッドをターゲットとする各ルールの影響を比較します。各保持ルールによって防止された最適化の割合を使用して、広範な保持ルールと狭い保持ルールを特定できます。
    1. 狭いルールが正確に記述されている場合(リフレクション アクセスされる正確なメンバーまたはクラスのみを保持している場合)、より広範な保持ルールを削除します。これにより、パッケージの残りの部分の R8 最適化が安全にロック解除されます。
    2. 広範なルールが適切なクラスをターゲットにしている場合は、広範なルールを残して、狭いルールを削除します。狭いルールは冗長なクラッタにすぎません。特定したクラス、フィールド、メソッドのみを対象とするように、広範なルールを絞り込んでください。

変更を検証してテストする: 構成アナライザーを再度実行して、競合が解決されたことを確認します。次に、リリースビルドをコンパイルし、変更をテストして、コードベースが想定どおりに動作することを確認します。

不要なルールを削除する

構成アナライザを使用すると、コードベースを体系的に監査して、構成を煩雑にする古い保持ルールを特定して削除できます。R8 構成アナライザは、不要なルールの主な原因を 2 つ特定します。

  • 未使用のルール: 現在のビルドでクラス、メソッド、フィールドのいずれにも一致しないルール。コードのリファクタリングや依存関係の削除後、または関連性のなくなったコピー&ペーストの構成から残ることが多く、不要な構成の複雑さを増大させます。
  • 同一のルール: 同一の保持ルールとは、同じクラス、フィールド、メソッドを対象とするルール、または同じ保持ルール ファイル内または複数の保持ルール ファイル間で保持ルールの宣言が重複しているルールを意味します。

どちらのタイプのルールも構成を複雑にし、メンテナンスやデバッグを困難にします。これらを特定することで、構成をクリーンアップできます。