Google は、黒人コミュニティに対する人種平等の促進に取り組んでいます。取り組みを見る

ART を設定する

このページでは、ART とそのコンパイル オプションを設定する方法について説明します。ここで扱うトピックは、システム イメージの事前コンパイルの構成、dex2oat のコンパイル オプション、システム パーティションおよびデータ パーティションの容量とパフォーマンスをトレードオフする方法などです。

ART の操作については、ART と DalvikDalvik 実行可能ファイルの形式、および source.android.com のその他のページをご覧ください。アプリが正しく動作することを確認するには、Android ランタイム(ART)でのアプリの動作確認をご覧ください。

ART の仕組み

ART は事前(AOT)コンパイルを使用し、Android 7.0(Nougat または N)以降では AOT コンパイル、ジャストインタイム(JIT)コンパイル、プロファイル ガイド付きコンパイルを組み合わせて使用します。これらすべてのコンパイル モードの組み合わせは構成可能です。以下のセクションではそれについて説明します。たとえば、Pixel デバイスの場合は、以下のコンパイル フローを使用して構成を行います。

  1. 最初に、アプリは AOT コンパイルなしでインストールされます。最初の数回の実行では、アプリはインタープリタによって解釈され、頻繁に実行されるメソッドは JIT コンパイルされます。
  2. デバイスがアイドル状態で充電中のときに、コンパイル デーモンが実行され、初回実行時に生成されたプロファイルに基づいて、頻繁に使用されるコードが AOT コンパイルされます。
  3. アプリを次に再起動すると、プロファイル ガイド付きコードが使用されます。これにより、コンパイル済みのメソッドについては実行時の JIT コンパイルが回避されます。新規の実行時に新たに JIT コンパイルされたメソッドはプロファイルに追加され、コンパイル デーモンによってピックアップされます。

ART は、コンパイラ(dex2oat ツール)と、Zygote を起動するためにロードされるランタイム(libart.so)で構成されます。dex2oat ツールは APK ファイルを受け取り、ランタイムが読み込む 1 つ以上のコンパイル アーティファクト ファイルを生成します。ファイルの数や拡張子、名前はリリースによって異なる場合がありますが、Android O 以降のリリースの場合、以下のファイルが生成されます。

  • .vdex: APK の非圧縮 DEX コードと、検証を高速化するための追加メタデータを格納します。
  • .odex: APK 内のメソッドの AOT コンパイル済みコードを含みます。
  • .art (optional): アプリの起動を高速化するために使用される、APK にリストされた文字列とクラスの ART 内部表現を格納します。

コンパイル オプション

ART のコンパイル オプションには、次の 2 つのカテゴリがあります。

  1. システム ROM 構成: システム イメージのビルド時にどのコードを AOT コンパイルするか。
  2. 実行時構成: ART がデバイス上でアプリをどのようにコンパイルして実行するか。

上記の 2 つのカテゴリを構成するコア ART オプションの一つは、コンパイラ フィルタです。コンパイラ フィルタは ART が DEX コードをコンパイルする方法を制御するオプションであり、dex2oat ツールに渡されます。Android O 以降、4 つのフィルタが公式にサポートされています。

  • verify: DEX コードの検証だけを実行します。
  • quicken: DEX コードの検証を実行し、DEX 命令の一部を最適化してインタープリタのパフォーマンスを向上させます。
  • speed: DEX コードの検証を実行し、すべてのメソッドを AOT コンパイルします。
  • speed-profile: DEX コードの検証を実行し、プロファイル ファイルにリストされているメソッドを AOT コンパイルします。

システム ROM 構成

システム ROM を構成する際は、いくつかの ART ビルド オプションを使用できます。これらのオプションを構成する方法は、/system の使用可能なストレージ容量と、プリインストールされたアプリの数に応じて決まります。システム ROM にコンパイルされる JAR / APK は、以下の 4 つのカテゴリに分けられます。

  • ブート クラスパス コード: デフォルトでは、speed コンパイラ フィルタでコンパイルされます。
  • システム サーバーコード: デフォルトでは、speed コンパイラ フィルタでコンパイルされます。
  • プロダクト固有のコアアプリ: デフォルトでは、speed コンパイラ フィルタでコンパイルされます。
  • 他のすべてのアプリ: デフォルトでは、quicken コンパイラ フィルタでコンパイルされます。

メイクファイル オプション

  • WITH_DEXPREOPT
  • dex2oat がシステム イメージにインストールされた DEX コードで呼び出されるかどうか。デフォルトで有効。

  • DONT_DEXPREOPT_PREBUILTS(Android L 以降)
  • DONT_DEXPREOPT_PREBUILTS を有効にすると、事前ビルド済みアプリの事前最適化を回避できます。そのようなアプリには、Gmail など、Android.mkinclude $(BUILD_PREBUILT) が指定されているアプリがあります。Google Play でアップデートされる可能性がある事前ビルド済みアプリの事前最適化をスキップすると、/system の容量は節約されますが、初回の起動時間が長くなります。

  • PRODUCT_DEX_PREOPT_DEFAULT_COMPILER_FILTER(Android 9 以降)
  • PRODUCT_DEX_PREOPT_DEFAULT_COMPILER_FILTER は、事前最適化済みアプリのデフォルトのコンパイラ フィルタを指定します。そのようなアプリには、Gmail など、Android.mkinclude $(BUILD_PREBUILT) が指定されているアプリがあります。コンパイラ フィルタを指定しないと、デフォルト値は quicken になります。

  • WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY(Android O MR1 で導入)
  • WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY を有効にすると、ブート クラスパスとシステム サーバーの JAR だけが事前最適化されます。

  • LOCAL_DEX_PREOPT
  • モジュール定義内で LOCAL_DEX_PREOPT オプションを指定することにより、個別のアプリ単位で事前最適化を有効 / 無効にすることもできます。これは、Google Play のアップデートによりシステム イメージ内の事前最適化済みコードが陳腐化する場合に備えて、アップデートを即座に受信する可能性があるアプリの事前最適化を無効にするのに有用な場合があります。また、データ パーティションに新しいバージョンのアプリがすでに存在する場合は、メジャー バージョン アップグレード OTA の容量を節約するためにも役立ちます。

    LOCAL_DEX_PREOPT では、true または false の値を使用して事前最適化を有効または無効にできます。また、事前最適化で APK または JAR ファイルから classes.dex ファイルを除去すべきでない場合は、除去しないことを指定できます。通常、このファイルは事前最適化後に不要になるため削除されます。サードパーティ APK 署名を有効なまま残すには、この nostripping オプションを指定する必要があります。

  • PRODUCT_DEX_PREOPT_BOOT_FLAGS
  • ブートイメージをコンパイルする方法を制御するオプションを dex2oat に渡します。これにより、カスタマイズ済みイメージクラス リスト、コンパイル済みクラスリスト、コンパイラ フィルタを指定できます。

  • PRODUCT_DEX_PREOPT_DEFAULT_FLAGS
  • ブートイメージ以外のすべてをコンパイルする方法を制御するオプションを dex2oat に渡します。

  • PRODUCT_DEX_PREOPT_MODULE_CONFIGS
  • 特定のモジュールとプロダクト構成を対象とする dex2oat オプションを渡す機能を提供します。これは、プロダクトの device.mk ファイルで $(call add-product-dex-preopt-module-config,<modules>,<option>) により設定されます。<modules> は、JAR ファイルでは LOCAL_MODULE、APK ファイルでは LOCAL_PACKAGE の名前のリストです。

  • PRODUCT_DEXPREOPT_SPEED_APPS (New in Android O)
  • プロダクトのコアとして識別され、speed コンパイラ フィルタでコンパイルすることが望ましいアプリのリスト。たとえば、SystemUI などの永続アプリがプロファイル ガイド付きコンパイルを使用できるのは次回のリブート時に限られます。したがって、プロダクトではそのようなアプリが常に AOT コンパイルされるようにする方が適切な場合があります。

  • PRODUCT_SYSTEM_SERVER_APPS (New in Android O)
  • システム サーバーによってロードされるアプリのリスト。これらのアプリは、デフォルトでは speed コンパイラ フィルタでコンパイルされます。

  • PRODUCT_ART_TARGET_INCLUDE_DEBUG_BUILD(Post Android O)
  • ART のデバッグ バージョンをデバイス上に配置するかどうか。デフォルトでは、userdebug および eng ビルドに対して有効になっています。この動作は、オプションを明示的に true または false に設定することでオーバーライドできます。

    デフォルトでは、デバイスは非デバッグ バージョン(libart.so)を使用します。 デバッグ バージョンに切り替えるには、システム プロパティ persist.sys.dalvik.vm.lib.2libartd.so に設定します。

  • WITH_DEXPREOPT_PIC (Removed in Android O)
  • Android 5.1.0 から Android 6.0.1 までのリリースの場合、WITH_DEXPREOPT_PIC を指定することで、位置独立コード(PIC)を有効化できます。これにより、イメージからコンパイルされたコードを /system から/data/dalvik-cache に再配置する必要がなくなり、データ パーティションの容量を節約できます。ただし、位置依存コードを利用する最適化が無効化されるため、実行時の影響がわずかにあります。一般的に、/data 内の容量の節約が求められるデバイスでは、PIC コンパイルを有効にしてください。

    Android 7.0 で、PIC コンパイルはデフォルトで有効化されるようになりました。

  • WITH_DEXPREOPT_BOOT_IMG_ONLY(Android O MR1 で削除)
  • このオプションは、WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY(システム サーバー JAR の事前最適化も行います)に置き換えられました。

ブート クラスパス構成

  • プリロード済みクラスリスト
  • プリロード済みクラスリストは、起動時に zygote が初期化するクラスのリストです。これにより、各アプリでクラス初期化子を個別に実行する必要がなくなり、初期化子の起動の高速化とメモリ内でのページの共有が可能になります。プリロード済みクラスリスト ファイルは、デフォルトでは frameworks/base/config/preloaded-classes にあり、一般的なスマートフォンで使用できるようにチューニングされたリストを含んでいます。ウェアラブル デバイスなどの他のデバイスではこれと異なる場合があり、それに応じてチューニングする必要があります。あまりにも多くのクラスを追加すると、使用されないクラスを読み込む際にメモリが浪費されるため、慎重にチューニングする必要があります。追加するクラスが少なすぎると、各アプリがそれ自身のコピーを持つことが必要になり、この場合もメモリが浪費されます。

    使用例(プロダクトの device.mk 内):

    PRODUCT_COPY_FILES += <filename>:system/etc/preloaded-classes
    

    注: この行は、build/target/product/base.mk からデフォルト メイクファイルを取得するプロダクト構成メイクファイルを継承する前に配置する必要があります。

  • イメージクラス リスト
  • イメージクラス リストは、dex2oat が事前に初期化して boot.art ファイルに格納するクラスのリストです。これにより、Zygote はプリロード時にこれらのクラスの初期化子を実行するのではなく、起動時に boot.art ファイルから結果を読み込むことができます。その重要な特徴は、イメージから読み込まれてプロセス間で共有されるページがクリーンで、低メモリの状況で簡単にスワップアウトできるようになることです。L の場合、イメージクラス リストは、デフォルトではプリロード済みクラスリストと同じリストを使用します。L より後の AOSP では、次のオプションでカスタム イメージクラス リストを指定できます。

    PRODUCT_DEX_PREOPT_BOOT_FLAGS
    

    使用例(プロダクトの device.mk 内):

    PRODUCT_DEX_PREOPT_BOOT_FLAGS += --image-classes=<filename>
    
  • コンパイル済みクラスリスト
  • L より後の AOSP では、コンパイル済みクラスリストを使用して、ブート クラスパスのクラスのサブセットを事前最適化の際にコンパイルすることを指定できます。このオプションは、デバイスの容量が非常に少なく、事前最適化されたブートイメージ全体に対応できない場合に有用な可能性があります。ただし、このリストで指定されないクラスは(デバイス上でも)コンパイルされないためインタープリタで解釈する必要があり、実行時のパフォーマンスに影響が及ぶ可能性があります。デフォルトでは、dex2oat は $OUT/system/etc/compiled-classes でコンパイル済みクラスリストを探し、device.mk がカスタムのリストをその場所にコピーできるようにします。特定のファイルの場所は、次のオプションで指定することもできます。

    PRODUCT_DEX_PREOPT_BOOT_FLAGS
    

    使用例(プロダクトの device.mk 内):

    PRODUCT_COPY_FILES += <filename>:system/etc/compiled-classes
    

    注: この行は、build/target/product/base.mk からデフォルト メイクファイルを取得するプロダクト構成メイクファイルを継承する前に配置する必要があります。

実行時構成

JIT のオプション

以下のオプションは、ART JIT コンパイラが利用できる場合に限り、Android リリースに影響します。

  • dalvik.vm.usejit: JIT を有効にするかどうか。
  • dalvik.vm.jitinitialsize(デフォルトは 64K): コード キャッシュの初期容量。コード キャッシュは定期的に GC が行われ、必要に応じて増加します。
  • dalvik.vm.jitmaxsize(デフォルトは 64M): コード キャッシュの最大容量。
  • dalvik.vm.jitthreshold(デフォルトは 10000): メソッドを JIT コンパイルするためにメソッドの「ホットネス」カウンタが渡さなければならないしきい値。「ホットネス」カウンタはランタイム内部の指標です。呼び出しの数や後方ブランチなどの要素を含みます。
  • dalvik.vm.usejitprofiles: JIT プロファイルが有効になっているかどうか。このオプションは dalvik.vm.usejit が false であっても使用できます。false の場合、コンパイラ フィルタ speed-profile はメソッドを AOT コンパイルせず、quicken と同じになります。
  • dalvik.vm.jitprithreadweight(デフォルトは dalvik.vm.jitthreshold / 20): アプリの UI スレッドの JIT「サンプル」の重み付け(jitthreshold を参照)。アプリを操作する際のユーザー エクスペリエンスに直接影響するメソッドのコンパイルを高速化するために使用します。
  • dalvik.vm.jittransitionweight(デフォルトは dalvik.vm.jitthreshold / 10): コンパイル コードとインタープリタ間を遷移するメソッド呼び出しの重み付け。高コストの遷移を最小限に抑えるため、関係するメソッドだけをコンパイルすることができます。

パッケージ マネージャーのオプション

Android 7.0 以降では、さまざまな段階で発生したコンパイル / 検証のレベルを指定する汎用的な方法があります。 コンパイル レベルは、次のデフォルト値を持つシステム プロパティで構成できます。

  • pm.dexopt.install=speed-profile
  • Google Play からアプリをインストールする際に使用されるコンパイル フィルタです。dex メタデータ ファイルで指定されたプロファイルを使用できるようにするには、インストール フィルタを speed-profile に設定することをおすすめします。プロファイルが指定されていない場合や空の場合は、speed-profile はquicken と同じになります。

  • pm.dexopt.bg-dexopt=speed-profile
  • デバイスがアイドル状態、充電中、完全に充電された状態の場合に使用されるコンパイル フィルタです。プロファイル ガイド付きコンパイルを利用してストレージの容量を節約するには、speed-profile コンパイラ フィルタをお試しください。

  • pm.dexopt.boot=verify
  • 無線(OTA)アップデート後に使用されるコンパイル フィルタ。起動に非常に長い時間がかかる事態を避けるため、このオプションで verify コンパイラ フィルタを指定することを強くおすすめします。

  • pm.dexopt.first-boot=quicken
  • デバイスの初回起動時に使用されるコンパイル フィルタ。 ここで使用されるフィルタは、工場出荷後の初回の起動時間にのみ影響します。ユーザーが初めてスマートフォンを使用する際の起動時間が長くなるのを避けるには、quicken フィルタの指定をおすすめします。なお、/system 内のすべてのアプリがすでに quicken コンパイラ フィルタでコンパイル済みである場合や、speed コンパイラ フィルタまたは speed-profile コンパイラ フィルタでコンパイルする場合、pm.dexopt.first-boot は効果を持ちません。

dex2oat オプション

上記のオプションのほとんどは事前最適化にのみ影響しますが、以下のオプションは事前最適化だけでなくデバイス上のコンパイルの際にも dex2oat に影響します。

ブートイメージをコンパイルする際に dex2oat を制御するオプション:

  • dalvik.vm.image-dex2oat-Xms: 初期ヒープサイズ
  • dalvik.vm.image-dex2oat-Xmx: 最大ヒープサイズ
  • dalvik.vm.image-dex2oat-filter: コンパイラ フィルタのオプション
  • dalvik.vm.image-dex2oat-threads: 使用するスレッドの数

ブートイメージ以外のすべてをコンパイルする際に dex2oat を制御するオプション:

  • dalvik.vm.dex2oat-Xms: 初期ヒープサイズ
  • dalvik.vm.dex2oat-Xmx: 最大ヒープサイズ
  • dalvik.vm.dex2oat-filter: コンパイラ フィルタのオプション

Android 6.0 までのリリースについては、ブートイメージ以外のすべてをコンパイルする際の追加オプションが 1 つ用されています。

  • dalvik.vm.dex2oat-threads: 使用するスレッドの数

Android 6.1 以降では、ブートイメージ以外のすべてをコンパイルする際の追加オプションが 2 つ用意されています。

  • dalvik.vm.boot-dex2oat-threads: 起動時に使用するスレッドの数
  • dalvik.vm.dex2oat-threads: 起動後に使用するスレッドの数

Android 7.1 以降では、ブートイメージ以外のすべてをコンパイルする際のメモリの使用方法を制御するオプションが 2 つ用意されています。

  • dalvik.vm.dex2oat-very-large: AOT コンパイルを無効化する最小合計 dex ファイルサイズ(バイト単位)
  • dalvik.vm.dex2oat-swap: dex2oat スワップ ファイルを使用(低メモリデバイス向け)

dex2oat の初期ヒープサイズと最大ヒープサイズを制御するオプションには、小さい値を指定しないでください。コンパイルできるアプリが制限される可能性があります。

Android 11 以降では、コンパイラ スレッドを特定の CPU グループに制限できる 3 つの CPU アフィニティ オプションが用意されています。

  • dalvik.vm.boot-dex2oat-cpu-set: 起動時に dex2oat スレッドを実行する CPU
  • dalvik.vm.image-dex2oat-cpu-set: ブートイメージのコンパイル中に dex2oat を実行する CPU
  • dalvik.vm.dex2oat-cpu-set: ブート後に dex2oat スレッドを実行する CPU

対象となる CPU は、カンマ区切りの CPU ID リストで指定します。たとえば、CPU 0~3 で dex2oat を実行する場合は、次のように設定します。

dalvik.vm.dex2oat-cpu-set=0,1,2,3

CPU アフィニティ プロパティを設定する場合、不要なメモリ競合や I/O 競合を避けるため、選択した CPU 数に一致するように、dex2oat スレッド数に対応するプロパティをマッチングすることをおすすめします。

dalvik.vm.dex2oat-cpu-set=0,1,2,3
dalvik.vm.dex2oat-threads=4

A/B 固有の構成

ROM の構成

Android 7.0 以降では、デバイスで 2 つのシステム パーティションを使用して A/B システム アップデートを有効にできます。システム パーティション サイズを節約するため、使用していない第 2 のシステム パーティションに事前最適化済みファイルをインストールできます。それらのファイルは、初回起動時にデータ パーティションにコピーされます。

使用例(device-common.mk 内):

PRODUCT_PACKAGES += \
     cppreopts.sh
PRODUCT_PROPERTY_OVERRIDES += \
     ro.cp_system_other_odex=1

デバイスの BoardConfig.mk 内:

BOARD_USES_SYSTEM_OTHER_ODEX := true

ブート クラスパス コード、システム サーバーコード、プロダクト固有のコアアプリは常にシステム パーティションにコンパイルされます。デフォルトでは、他のすべてのアプリは、使用されていない第 2 のシステム パーティションにコンパイルされます。これは SYSTEM_OTHER_ODEX_FILTER で制御できます。そのデフォルト値は次のとおりです。

SYSTEM_OTHER_ODEX_FILTER ?= app/% priv-app/%

バックグラウンド dexopt OTA

A/B 対応デバイスでは、アプリをバックグラウンドでコンパイルして新しいシステム イメージにアップデートできます。オプションとして、コンパイル スクリプトおよびバイナリをシステム イメージに組み込むことができます。バックグラウンドでのアプリのコンパイルをご覧ください。このコンパイルに使用されるコンパイル フィルタは、次のように制御されます。

pm.dexopt.ab-ota=speed-profile

プロファイル ガイド付きコンパイルを利用してストレージの容量を節約するため、speed-profile を使用することをおすすめします。