Android 4.4に入ったARTのソースを見た感想

Android 4.4 (Kitkat) のソースコードが公開されました。話によるとDalvikを置き換えるARTというものが開発者向けに使えるようになっているそうです。面白そうなので調べてみました。以下は全て推測と個人の感想です。

ART とは

公式な情報はこれ
https://source.android.com/devices/tech/dalvik/art.html

  • Dalvikと置きかえて使えるランタイム
  • まだ開発中。開発者のフィードバックを得るために公開した
  • Dalvikがデフォルトであると強調。

Dalvikのランタイムはlibdvm.soで、ARTではそれがlibart.soに置き換わるらしい。開発者メニューでどちらを使うのか切り替えることができるようだ。

http://gigaom.com/2013/10/22/google-buys-frances-flexycore-for-better-performing-android/
GoogleはフランスのFlexyCoreという会社を買収したそうです。ARTはこの会社の成果という噂もありますが、定かではありません。
2013.11.10修正
Android 4.4のARTは外から買ってきたものではなくて、2年前からgoogle内部で開発してきたもの。gitのログを見るとそれを確認できます。

Android 4.4のソースコードを見る

手軽なのはこれ。(ありがとう、のりつなさん)
http://tools.oesf.biz/android-4.4.0_r1.0/

自分でソースコードをダウンロードするには、公式サイトの方法を見ながら、Android 4.4を指定してrepo initします。

$ repo init -u https://android.googlesource.com/platform/manifest -b android-4.4_r1

なお、何も無い状態からrepo syncすると時間もかかるしネットワークの帯域を使って迷惑になるので、すでに前のバージョンをrepo syncしたことのある人はそのリポジトリを再利用しましょう。
KMC Staff Blog:Androidのrepo syncのTips

ARTのソースコードをながめながらつぶやいた

ARTのソースはトップディレクトリの直下のartにあります。
http://tools.oesf.biz/android-4.4.0_r1.0/xref/art/
全てc++で書かれていますが、ファイル名のサフィックスは*.ccです。Dalvikではc++のファイルのサフィックスは*.cppなので、両者は全く違うチームで開発されたのではないでしょうか。

compilerのディレクトリの下にllvmというディレクトリがあります。そこにあるファイルの名前から想像して、arm, thumb2, x86用のコードを生成するようです。
そのコメントはこれ。もともとは独自フォーマットだったけど、、今はELF dynamic objectと書いてあります。
ここにwhileループの中の巨大なswitch文という素朴なDEXコードインタプリタの実装があります。Dalvikの中のインタプリタはアセンブラでカリカリにチューニングされ、実行頻度の高い部分を見つけてJITコンパイルを要求するようになっていますが、これにはそのような気配はありません。実行中にバックグランドでコンパイルするということはなさそうです。
oatファイルはdexファイルを置き換えるものではなくて、dexファイルと併用するようです。
libart-compilerのライブラリはどこで使われているかを調べましたが、dex2oatコマンドだけがlibart-compilerをリンクしていました。つまり、dexファイルをコンパイルする(=oatファイルを生成する)にはdex2oatコマンドを実行する必要があります。
dex2oatコマンドのオプションを見ると、--bitcode=を指定すると、LLVMのbitcodeをファイルとして保存できることがわかります。ARTではdexコードからbitcodeへのフロントエンドを開発し、bitcodeでの最適化やbitcodeからARMã‚„x86のELFフォーマットのコード生成の部分はLLVMのモジュールがほぼそのまま使用できるようになっていると思われます。
AndroidではまだJava6を使用していますが、これはすでにEOL(End of Life)です。Oracleとの係争もありますし、Javaからのスイッチもありえますね。(個人の感想です。)
runtime/class_linker.cc#GenerateOatFileでdex2oatコマンドをforkしてexecしてます。そして、この関数の呼び出し元を上にたどっていくとopenDexFileNativeという関数にたどりつきます。その検索結果。これがlibdvm.soとlibart.soの共通のAPIになっているのでしょう。
runtime/class_linker.cc#FindOrCreateOatFileForDexLocationLockedの中で、その名の通り、oatファイルが見つかればそれを使用し、無ければdexファイルをコンパイルしてoatファイルを生成しています。
emulatorをビルドしてみましたが、ビルドされたファイルの中に*.oatファイルはありませんでした。でもcleanするときに*.oatファイルを削除するコードはあったので、Makefileのどこかをいじればビルド時にホスト側でdex2oatコマンドを実行することはできるのではないかと思います。
アプリケーションをインストールして、最初に起動したときにdex2oatコマンドでコンパイルが行われるので少し時間がかかるという挙動になると思います。

DalvikVMのJITとの比較

Android 2.2 (Froyo)から入ったDalvikVMのJITについて以前ここに書きました。
KMC Staff Blog:AndroidのFroyoのJITについて
http://togetter.com/li/16674
インタプリタで実行中に実行頻度の高い部分を検出して、その部分だけをコンパイルして置き換えます。コンパイルは専用のスレッドでバックグランドで行います。小さい単位でコンパイルすることで、コンパイル時間も短く、使用メモリの増加もおさえられています。コンパイル結果は保存せず、アプリの起動のたびにJITが行われます。
現状のARTではコンパイルは実行の直前にdexファイル単位で行われます。コンパイルにかかる時間、使用メモリはDalvikのJITよりも大きいと思います。コンパイルした結果はoatファイルとして保存されますが、このファイルのサイズは元のdexファイルの数倍はあると思われます。

DalvikVMのJITの限界とLLVMのポテンシャル

DalvikVMのJITはよくできていると思うのですが、限界もあります。それは強力な最適化を行うことが難しいということです。最近のコンパイル技術のホットな話題として、並列性を自動的に検出し、それをスレッドに分割したりベクタライズしてSIMD命令を使用したりします。DalvikVMのJITではそこまでの最適化はできません。最近のAndroidで使用するSoCではNEON命令は標準装備、4コアのSMPもめずらしくありませんが、それらをフル活用することができないのです。搭載するメモリ、ストレージの容量も大きくなって実機上で本格的な最適化コンパイラを動かす余地も出てきました。
このことに関してはGoogleも気がついていて、Android4.0ではLLVM/Clangの技術を使ったRenderScriptが入りましたが、傍流のままでした。そこで、主力であるDalvikVMをLLVMのコンパイル技術をフルに活用できるARTへの置き換えを狙っているのだと思います。

現在のARTはまだまだ完成形ではありません。とにかくまずつなげてみたというレベルであり、LLVMの最適化を効果的に使える状態ではありません。この先の発展に注目したいと思います。

Android 4.0でのRenserScriptについてはここに書きました。
KMC Staff Blog:Android 4.0で利用されているLLVM

いまどきのコンパイラは普通のループもベクタライズしてSIMD命令生成することができます。これはgccの例ですが、LLVMも同様のことが可能。
KMC Staff Blog:ARMのNEONのSIMD命令をgccのオートベクタライズの最適化で使う方法

LLVMでの驚きの最適化
clang+llvmでさりげなくすごいコードが生成されていた話。 - 組み込みの人。

おまけ:DalvikとARTをコマンドラインで切り替えるには

root権限でsetprop persist.sys.dalvik.vm.lib libart.so をしてからリブートします。

$ adb root && sleep 3
$ adb shell setprop persist.sys.dalvik.vm.lib libart.so
$ adb reboot

http://tools.oesf.biz/android-4.4.0_r1.0/xref/art/Android.mk#346

追記

ARTの中にもガベージコレクタがありますが、DalvikVMと同様にコンカレントGCのようです。

ここに書いたことはソースを見た感想であり、実際に動かしてみたわけではありません。実際に動かしてDalvikとARTを比較した人がいたら情報をください。

続きの記事を書きました。
Android 4.4 のARTのブートログを見てみた - 組み込みの人。