33
進化するART DroidKaigi 2015/4/25 僻地のプログラマkmt-t

進化するArt

  • Upload
    kmt-t

  • View
    12.549

  • Download
    0

Embed Size (px)

Citation preview

進化するART

DroidKaigi

2015/4/25

僻地のプログラマkmt-t

1

自己紹介

• ハンドルネーム

– @kmt_t

• 職業

– 業務系プログラマ

– 元組み込み系

• 専門分野

– 画像処理、ファイルシステム、仮想マシン

– 最近は自然言語処理、ディープラーニング

書籍出版中!

• 「Androidの仮想マシン Dalvik編」発売中

– 達人出版会様より出版!

– ARTを攻略するにはまずDalvikから!

2

今日話す内容

• ARTの概要

• ARTの実行ファイル

• ARTのコンパイラ

• 今回解説するのはバージョン5.1.0_r1.0

3

今日話す内容

• ARTの概要

• ARTの実行ファイル

• ARTのコンパイラ

• 今回解説するのはバージョン5.1.0_r1.0

4

注意!コードがかなり頻繁に変わるので将来的に正しい保証はありません

ARTの概要

5

ARTとは何か?

• (ART = Android RunTime)

• ランタイムとは

– アプリケーション実行環境

– コアライブラリ

• Androidのランタイムとは

– Dalvikバイトコードの実行環境

– KitKatまではDalvik

– LolipopからはART

6

ARTの特徴

• コードの変更点

– Dalvikから完全書き換え

– プログラミングはC言語からC++11

• アーキテクチャの変更点

– JITコンパイラからAOTコンパイラに

• バイトコードを機械語にコンパイル

• AOTコンパイラでアプリケーションインストール時にコンパイルするように変更

– ガベージコレクションが改善

– 64bitCPU対応

7

ベンチマーク

8

出典 : http://gigazine.net/news/20140406-nexus-5-art/

ART Dalvik

ARTの実行ファイル

9

ARTの実行ファイル

• OATファイル

– AOTコンパイラが出力する実行ファイル

– 機械語はOATファイルに保存

• DEXファイル

– OATファイルに埋め込まれる

– メタデータはDEXファイルをそのまま使用

– 「Androidの仮想マシンDalvik編」参照

10

OATファイルの概要

• ELF形式

– Linuxでは一般的に使われている形式

– OATファイルは共有ライブラリ

• リンカとローダはART独自

– リンカ、ローダとは?

– メモリへ展開

– アドレスの再配置

– シンボルの解決

– 詳細は「Linkers & Loaders」参照

11

ELFの概要

• 以下のブロックに分割

– ELFヘッダ

– プログラムヘッダ

• セグメント情報

– セグメント

– セクション

– セクションヘッダ

• セクション情報

• セグメントとセクションは同じ領域を別の論理単位に分割

12

ELFヘッダ

プログラムヘッダ

セグメントまたは

セクション

セクションヘッダ

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独自のセクション

.rodataセクション

• DEXファイルとガイド情報

14

アイテム名 内容

OatHeader .rodataに保存されているデータのヘッダ

OatDexFile DEXファイルをmmapするファイル名の配列

Dex DEXファイルの配列 (DEXファイルそのもの)

OatClass クラスに紐付けられたコンパイル済みメソッドの位置

GcMap ガベージコレクションのガイド情報

VmapTable 仮想マシンのレジスタに格納されている値の型

MappingTable CPUと仮想マシンのプログラムカウンタの対応表

.oat_patchesセクション

• イメージファイルの再配置情報

• イメージファイルとは?

– イメージファイルはアプリケーション起動時にImageSpaceヒープにロードされる

– イメージファイルはロードされるたびにアドレスを変更するため、再配置が必要

• ImageSpaceヒープに含まれるデータ

– 定数文字列、クラスメタデータ、メソッドメタデータのJavaオブジェクトインスタンス

• 通常のELFファイルには含まれない

15

.textセクション

• コンパイルされたメソッドの機械語

16

その他セクション (一般的な使い方)

• .dynsimセクション

– 動的リンクのシンボルテーブル

• .dynstrセクション

– .dynsymのシンボル文字列テーブル

• .hashセクション

– シンボル検索用のハッシュテーブル

– 一般的にはリンカ、ローダ用

– リンカ、ローダが独自実装であるARTでは使用しない

• .dynamic

– 動的リンクシンボル検索用のハッシュテーブル

– 一般的にはリンカ、ローダ用

– リンカ、ローダが独自実装であるARTでは使用しない

17

ARTのコンパイラ

18

3つのコンパイラ

• Quickコンパイラ

– DalvikのJITコンパイラベース

• Portableコンパイラ

– LLVMベース

• Seaコンパイラ

– LLVM IRの上にSea IRのレイヤを追加

19

3つのコンパイラ

• Quickコンパイラ

– DalvikのJITコンパイラベース

20

Quickコンパイラの特徴

• Quickコンパイラは

– DalvikのJITコンパイラベース

– DalvikのJITコンパイラを先に理解する

– 「Androidの仮想マシン Dalvik編」参照

• ARTが速くなったのは何故?

– コンパイラ方式が変更、だけではない!

– ランタイム全体の改善

– メモリアロケータの高速化

– ガベージコレクションの高速化

21

Quickコンパイラのアーキテクチャ

22

バイトコード

MIR

最適化

LIR

機械語

•バイトコードに近い表現•基本ブロックに分割•レジスタをSSA形式に変換•制御フローダイアグラム、支配木に変換

•ほとんどの最適化はここでやる

•機械語に近い表現•ただし機械語独立

•コンパイル済みコード

コンパイラの基本用語

• SSA (静的単一代入)

– 仮想マシンレジスタ番号に添え字を付ける

– 代入されるごとに添え字を増加

– 添え字の違う仮想マシンレジスタは別物

• 基本ブロック

– 途中でジャンプしない

– 途中にジャンプされない

– 連続したプログラムのブロック

23

制御フローダイアグラム (CFD)

• 基本ブロックの分岐をグラフ化したもの

• コードやレジスタの生死の判定で使用

24

基本ブロックM

基本ブロックL

基本ブロックN

基本ブロックO

基本ブロックP

If true If false

支配木

• ある基本ブロックの前に必ず通る基本ブロックのことを「支配する」

• SSAの最適化で使用

• 「MはNを支配する」

25

基本ブロックM

基本ブロックL

基本ブロックN

基本ブロックO

基本ブロックP

If true If false

最適化一覧 (1/2)

手法 DX Dalvik ART

エスケープ解析 (配列オブジェクトの消去) ○ × ×

Pruned-SSA ○ ○ ○

定数伝播 ○ ○ ○

定数畳み込み ○ × ×

定数集約 (同じ定数のロードを一カ所に) ○ × ○

基本帰納変数による計算の簡略化 × ○ ×

ループ不変式の移動 × ○ ○

インライン展開 × ○ ○

死んだコードの除去 ○ ○ ○

無駄な仮想マシンレジスタ複製の除去 ○ × ○

リテラルの命令埋め込み ○ × ×

26

最適化一覧 (2/2)

手法 DX Dalvik ART

無駄なNULLチェックの除去 × × ○

無駄なクラス初期化チェックの除去 × × ○

32bit整数以外の比較とジャンプ命令の結合 × × ○

フィールドオフセットの命令埋め込み × × ○

反仮想化 (仮想メソッドの仮想化除去) × × ○

基本ブロックの並びの最適化 × × ○

無駄な例外ハンドラの除去 × × ○

無駄なメモリロードの抑止 × ○ ○

仮想マシンレジスタのCPUレジスタへの昇格 × × ○

無駄なCPUレジスタ複製の抑止 × × ○

CPUレジスタ割り当ての重み付け (移動コストや使用頻度の高いCPUレジスタは破棄されない)

× × ○

27

ARTのコンパイラの利点

• JITコンパイラよりパフォーマンスがよい

– 実行時のオーバーヘッドがない

– 時間のかかる最適化が可能である

• ART固有の最適化が可能である

– LLVMを使うと最適化が難しいケースがある

• C++11を使っているためコードが簡略化

28

ARTのコンパイラの欠点

• 多くの最適化をMIRでやる

– CPUアーキテクチャ依存の機械語レベルの最適化は皆無

– 機械語レベルの最適化はCPUアーキテクチャに依存しており、開発工数がかかる

– DalvikではLIRがCPUアーキテクチャ依存だったがARTは非依存

– DalvikではIntelがx86向けの機械語の最適化コードをコントリビュートしていた

29

まとめ

• 実行ファイル

– ELF形式である

– ART独自のデータが含まれる

– ART独自のリンカとローダ

• コンパイラ

– DalvikのJITコンパイラベース

– LLVMはつかっていない

– CPUアーキテクチャ依存の最適化は若干弱い

• コード変更が頻繁であり「進化してる」

30

まとめ

• 実行ファイル

– ELF形式である

– ART独自のデータが含まれる

– ART独自のリンカとローダ

• コンパイラ

– DalvikのJITコンパイラベース

– LLVMはつかっていない

– CPUアーキテクチャ依存の最適化は若干弱い

• コード変更が頻繁であり「進化してる」

31

マスターブランチとkitkat-mr1-releaseブランチの差分

$ git diff 21b2216e4aa3756b5f96a587e99ac4fd0b16b844 | wc -l

539703

ご清聴ありがとうございました

• 質問はありますか?

32