Successfully reported this slideshow.

進化するArt

36

Share

Loading in …3
×
1 of 33
1 of 33

More Related Content

Related Books

Free with a 14 day trial from Scribd

See all

Related Audiobooks

Free with a 14 day trial from Scribd

See all

進化するArt

  1. 1. 進化するART DroidKaigi 2015/4/25 僻地のプログラマkmt-t
  2. 2. 1 自己紹介 • ハンドルネーム – @kmt_t • 職業 – 業務系プログラマ – 元組み込み系 • 専門分野 – 画像処理、ファイルシステム、仮想マシン – 最近は自然言語処理、ディープラーニング
  3. 3. 書籍出版中! • 「Androidの仮想マシン Dalvik編」発売中 – 達人出版会様より出版! – ARTを攻略するにはまずDalvikから! 2
  4. 4. 今日話す内容 • ARTの概要 • ARTの実行ファイル • ARTのコンパイラ • 今回解説するのはバージョン5.1.0_r1.0 3
  5. 5. 今日話す内容 • ARTの概要 • ARTの実行ファイル • ARTのコンパイラ • 今回解説するのはバージョン5.1.0_r1.0 4 注意! コードがかなり頻繁に変わるので 将来的に正しい保証はありません
  6. 6. ARTの概要 5
  7. 7. ARTとは何か? • (ART = Android RunTime) • ランタイムとは – アプリケーション実行環境 – コアライブラリ • Androidのランタイムとは – Dalvikバイトコードの実行環境 – KitKatまではDalvik – LolipopからはART 6
  8. 8. ARTの特徴 • コードの変更点 – Dalvikから完全書き換え – プログラミングはC言語からC++11 • アーキテクチャの変更点 – JITコンパイラからAOTコンパイラに • バイトコードを機械語にコンパイル • AOTコンパイラでアプリケーションインストール 時にコンパイルするように変更 – ガベージコレクションが改善 – 64bitCPU対応 7
  9. 9. ベンチマーク 8 出典 : http://gigazine.net/news/20140406-nexus-5-art/ ART Dalvik
  10. 10. ARTの実行ファイル 9
  11. 11. ARTの実行ファイル • OATファイル – AOTコンパイラが出力する実行ファイル – 機械語はOATファイルに保存 • DEXファイル – OATファイルに埋め込まれる – メタデータはDEXファイルをそのまま使用 – 「Androidの仮想マシンDalvik編」参照 10
  12. 12. OATファイルの概要 • ELF形式 – Linuxでは一般的に使われている形式 – OATファイルは共有ライブラリ • リンカとローダはART独自 – リンカ、ローダとは? – メモリへ展開 – アドレスの再配置 – シンボルの解決 – 詳細は「Linkers & Loaders」参照 11
  13. 13. ELFの概要 • 以下のブロックに分割 – ELFヘッダ – プログラムヘッダ • セグメント情報 – セグメント – セクション – セクションヘッダ • セクション情報 • セグメントとセクションは同じ領域を別 の論理単位に分割 12 ELFヘッダ プログラムヘッダ セグメント または セクション セクションヘッダ
  14. 14. OATファイルをobjdumpする 13 # arm-linux-androideabi-objdump -h ./boot.oat ./boot.oat: file format elf32-littlearm Sections: Idx Name Size VMA LMA File off Algn 0 .dynsym 00000040 709780f4 709780f4 000000f4 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 1 .dynstr 00000026 70978134 70978134 00000134 2**0 CONTENTS, ALLOC, LOAD, READONLY, DATA 2 .hash 00000020 7097815c 7097815c 0000015c 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 3 .rodata 01a50000 70979000 70979000 00001000 2**12 CONTENTS, ALLOC, LOAD, READONLY, DATA ※ ART独自のデータ含む 4 .text 01499d80 723c9000 723c9000 01a51000 2**12 CONTENTS, ALLOC, LOAD, READONLY, CODE 5 .dynamic 00000038 73863000 73863000 02eeb000 2**12 CONTENTS, ALLOC, LOAD, READONLY, DATA 6 .oat_patches 001af258 00000000 00000000 02eeb038 2**3 CONTENTS, READONLY ※ ART独自のセクション
  15. 15. .rodataセクション • DEXファイルとガイド情報 14 アイテム名 内容 OatHeader .rodataに保存されているデータのヘッダ OatDexFile DEXファイルをmmapするファイル名の配列 Dex DEXファイルの配列 (DEXファイルそのもの) OatClass クラスに紐付けられたコンパイル済みメソッドの位置 GcMap ガベージコレクションのガイド情報 VmapTable 仮想マシンのレジスタに格納されている値の型 MappingTable CPUと仮想マシンのプログラムカウンタの対応表
  16. 16. .oat_patchesセクション • イメージファイルの再配置情報 • イメージファイルとは? – イメージファイルはアプリケーション起動時 にImageSpaceヒープにロードされる – イメージファイルはロードされるたびにアド レスを変更するため、再配置が必要 • ImageSpaceヒープに含まれるデータ – 定数文字列、クラスメタデータ、メソッドメ タデータのJavaオブジェクトインスタンス • 通常のELFファイルには含まれない 15
  17. 17. .textセクション • コンパイルされたメソッドの機械語 16
  18. 18. その他セクション (一般的な使い方) • .dynsimセクション – 動的リンクのシンボルテーブル • .dynstrセクション – .dynsymのシンボル文字列テーブル • .hashセクション – シンボル検索用のハッシュテーブル – 一般的にはリンカ、ローダ用 – リンカ、ローダが独自実装であるARTでは使用しない • .dynamic – 動的リンクシンボル検索用のハッシュテーブル – 一般的にはリンカ、ローダ用 – リンカ、ローダが独自実装であるARTでは使用しない 17
  19. 19. ARTのコンパイラ 18
  20. 20. 3つのコンパイラ • Quickコンパイラ – DalvikのJITコンパイラベース • Portableコンパイラ – LLVMベース • Seaコンパイラ – LLVM IRの上にSea IRのレイヤを追加 19
  21. 21. 3つのコンパイラ • Quickコンパイラ – DalvikのJITコンパイラベース 20
  22. 22. Quickコンパイラの特徴 • Quickコンパイラは – DalvikのJITコンパイラベース – DalvikのJITコンパイラを先に理解する – 「Androidの仮想マシン Dalvik編」参照 • ARTが速くなったのは何故? – コンパイラ方式が変更、だけではない! – ランタイム全体の改善 – メモリアロケータの高速化 – ガベージコレクションの高速化 21
  23. 23. Quickコンパイラのアーキテクチャ 22 バイトコード MIR 最適化 LIR 機械語 •バイトコードに近い表現 •基本ブロックに分割 •レジスタをSSA形式に変換 •制御フローダイアグラム、支配木に変換 •ほとんどの最適化はここでやる •機械語に近い表現 •ただし機械語独立 •コンパイル済みコード
  24. 24. コンパイラの基本用語 • SSA (静的単一代入) – 仮想マシンレジスタ番号に添え字を付ける – 代入されるごとに添え字を増加 – 添え字の違う仮想マシンレジスタは別物 • 基本ブロック – 途中でジャンプしない – 途中にジャンプされない – 連続したプログラムのブロック 23
  25. 25. 制御フローダイアグラム (CFD) • 基本ブロックの分岐をグ ラフ化したもの • コードやレジスタの 生死の判定で使用 24 基本 ブロックM 基本 ブロックL 基本 ブロックN 基本 ブロックO 基本 ブロックP If true If false
  26. 26. 支配木 • ある基本ブロックの前に 必ず通る基本ブロックの ことを「支配する」 • SSAの最適化で使用 • 「MはNを支配する」 25 基本 ブロックM 基本 ブロックL 基本 ブロックN 基本 ブロックO 基本 ブロックP If true If false
  27. 27. 最適化一覧 (1/2) 手法 DX Dalvik ART エスケープ解析 (配列オブジェクトの消去) ○ × × Pruned-SSA ○ ○ ○ 定数伝播 ○ ○ ○ 定数畳み込み ○ × × 定数集約 (同じ定数のロードを一カ所に) ○ × ○ 基本帰納変数による計算の簡略化 × ○ × ループ不変式の移動 × ○ ○ インライン展開 × ○ ○ 死んだコードの除去 ○ ○ ○ 無駄な仮想マシンレジスタ複製の除去 ○ × ○ リテラルの命令埋め込み ○ × × 26
  28. 28. 最適化一覧 (2/2) 手法 DX Dalvik ART 無駄なNULLチェックの除去 × × ○ 無駄なクラス初期化チェックの除去 × × ○ 32bit整数以外の比較とジャンプ命令の結合 × × ○ フィールドオフセットの命令埋め込み × × ○ 反仮想化 (仮想メソッドの仮想化除去) × × ○ 基本ブロックの並びの最適化 × × ○ 無駄な例外ハンドラの除去 × × ○ 無駄なメモリロードの抑止 × ○ ○ 仮想マシンレジスタのCPUレジスタへの昇格 × × ○ 無駄なCPUレジスタ複製の抑止 × × ○ CPUレジスタ割り当ての重み付け (移動コストや 使用頻度の高いCPUレジスタは破棄されない) × × ○ 27
  29. 29. ARTのコンパイラの利点 • JITコンパイラよりパフォーマンスがよい – 実行時のオーバーヘッドがない – 時間のかかる最適化が可能である • ART固有の最適化が可能である – LLVMを使うと最適化が難しいケースがある • C++11を使っているためコードが簡略化 28
  30. 30. ARTのコンパイラの欠点 • 多くの最適化をMIRでやる – CPUアーキテクチャ依存の機械語レベルの最 適化は皆無 – 機械語レベルの最適化はCPUアーキテクチャ に依存しており、開発工数がかかる – DalvikではLIRがCPUアーキテクチャ依存だっ たがARTは非依存 – DalvikではIntelがx86向けの機械語の最適化 コードをコントリビュートしていた 29
  31. 31. まとめ • 実行ファイル – ELF形式である – ART独自のデータが含まれる – ART独自のリンカとローダ • コンパイラ – DalvikのJITコンパイラベース – LLVMはつかっていない – CPUアーキテクチャ依存の最適化は若干弱い • コード変更が頻繁であり「進化してる」 30
  32. 32. まとめ • 実行ファイル – ELF形式である – ART独自のデータが含まれる – ART独自のリンカとローダ • コンパイラ – DalvikのJITコンパイラベース – LLVMはつかっていない – CPUアーキテクチャ依存の最適化は若干弱い • コード変更が頻繁であり「進化してる」 31 マスターブランチとkitkat-mr1-releaseブランチの差分 $ git diff 21b2216e4aa3756b5f96a587e99ac4fd0b16b844 | wc -l 539703
  33. 33. ご清聴ありがとうございました • 質問はありますか? 32

Editor's Notes

  • 人が多いので緊張します。
    発表時間が短いので話すペースは早めですが、スライドはあとでSlideShareにあげるのでご確認ください。
    ベースとなる知識がないと難しい内容かも知れませんががんばりましょう。
  • 他の登壇者が自己紹介見るとすごい人ばかり何ですが、自分はただのおっさんです。
    仕事Android全然関係ありません。
  • 今日はARTの発表が二本ありますが、今日の発表とこの本を読むことで誰でもARTのソースを読むベースになります。
    断言しますがDalvikわかってないとART理解するのはかなり無理ゲーです。

    一応ART編も書く予定です。
  • 発表する内容としてはひたすらソースコードを読んで作った発表なので、むしろコードの臭いしかしない発表になります。

    みなさんが興味のありそうなところをチョイスしました。
    ガベージコレクションについてはこの次のセッション聴いてください。

    今日のイベントは落ちないアプリの発表がいくつかありますが、一言
    DalvikのときもそうだったんですがARTもVM側にバグがありそうなので、絶対落ちないアプリとかIt’s dreamと言っておきます。
    お前たちハイレイヤーどものソフトの安定度は我々が支配している!
    はっはっはっは
  • 発表する内容としてはひたすらソースコードを読んで作った発表なので、むしろコードの臭いしかしない発表になります。

    みなさんが興味のありそうなところをチョイスしました。
    ガベージコレクションについてはこの次のセッション聴いてください。

    今日のイベントは落ちないアプリの発表がいくつかありますが、一言
    DalvikのときもそうだったんですがARTもVM側にバグがありそうなので、絶対落ちないアプリとかIt’s dreamと言っておきます。
    お前たちハイレイヤーどものソフトの安定度は我々が支配している!
    はっはっはっは
  • Gigazineさんのサイトからの引用です
  • 再配置とは実行ファイルをメモリに展開したときに展開したアドレスにあわせてプログラム中のメモリアドレスを書き換える処理です。実行ファイルは毎回同じメモリアドレスにロードされるとは限りません。
    シンボルの解決は説明しない
  • 先ほども説明しましたが再配置とは実行ファイルをメモリに展開したときに展開したアドレスにあわせてプログラム中のメモリアドレスを書き換える処理です。

    昔はこれらのオブジェクトのインスタンスの生成は実際に必要とするまで遅延していました。
    ARTではアプリケーション起動前に生成します。
  • 通常のLinuxの使われ方と一緒なので割愛します。
    興味のある人はネットで調べるかLinkers&Loadersをご覧ください
  • たしかにAOTコンパイラになって最適化は増えているがすべてではない
  • まずARTのコンパイラの構造について説明します。
    構造としてはDalvikのJITコンパイラとかなり似通っています。
    (説明する)
    基本ブロック、SSA、制御フローダイアグラム、支配木とは何でしょうか?
  • 制御フローダイアグラム、支配木、データフロー分析などはドラゴンブックのようなコンパイラの教科書や自分の本を読まないと理解できません。
    アーキテクチャの解説は以上で終わりです。
  • DXはJavaバイトコードからDalvikバイトコードにコンパイルするコンパイラで、ここでも最適化されています。
  • 発表時間が短いので一個だけ解説します。
    この中で最適化の例として反仮想化に注目して解説します。

    Javaのメソッドは基本的に仮想メソッドでオーバーライドができます。
    実行時にはvtableをつかってメソッドを検索する処理が入ります。
    反仮想化ではぜったいこのメソッドが呼ばれてオーバーライドされないのが
    わかっている場合にそのメソッドを直接呼びます。

    性能的には結構効く最適化のはずです。
  • DalvikではC++じゃないせいで変なコードが結構ありました。
  • CPUアーキテクチャ非依存とはx86、ARM、MIPすべて同じコードと言うことです。
    Interlのライブラリはlibencode
  • ×