Upload
kmt-t
View
12.549
Download
0
Embed Size (px)
Citation preview
1
自己紹介
• ハンドルネーム
– @kmt_t
• 職業
– 業務系プログラマ
– 元組み込み系
• 専門分野
– 画像処理、ファイルシステム、仮想マシン
– 最近は自然言語処理、ディープラーニング
今日話す内容
• ARTの概要
• ARTの実行ファイル
• ARTのコンパイラ
• 今回解説するのはバージョン5.1.0_r1.0
4
注意!コードがかなり頻繁に変わるので将来的に正しい保証はありません
ARTとは何か?
• (ART = Android RunTime)
• ランタイムとは
– アプリケーション実行環境
– コアライブラリ
• Androidのランタイムとは
– Dalvikバイトコードの実行環境
– KitKatまではDalvik
– LolipopからはART
6
ARTの特徴
• コードの変更点
– Dalvikから完全書き換え
– プログラミングはC言語からC++11
• アーキテクチャの変更点
– JITコンパイラからAOTコンパイラに
• バイトコードを機械語にコンパイル
• AOTコンパイラでアプリケーションインストール時にコンパイルするように変更
– ガベージコレクションが改善
– 64bitCPU対応
7
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
その他セクション (一般的な使い方)
• .dynsimセクション
– 動的リンクのシンボルテーブル
• .dynstrセクション
– .dynsymのシンボル文字列テーブル
• .hashセクション
– シンボル検索用のハッシュテーブル
– 一般的にはリンカ、ローダ用
– リンカ、ローダが独自実装であるARTでは使用しない
• .dynamic
– 動的リンクシンボル検索用のハッシュテーブル
– 一般的にはリンカ、ローダ用
– リンカ、ローダが独自実装であるARTでは使用しない
17
3つのコンパイラ
• Quickコンパイラ
– DalvikのJITコンパイラベース
• Portableコンパイラ
– LLVMベース
• Seaコンパイラ
– LLVM IRの上にSea IRのレイヤを追加
19
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