October 1, 2014 · Android

Layout Class Performance

〜 "FrameLayout" vs "LinearLayout" vs "RelativeLayout" Performance 〜

こんにちは @wasabeef_jpです。

Androidでlayout.xmlを実装していて、疑問があったので、調査して纏めてみました。

Androidでは、Layoutの最適化としてRelativeLayoutで、階層を浅くした方がいいというのはDeveloper Androidにも書いてある通りに有名な話ですが
参考: Optimizing Layout Hierarchies

Layoutの中にListViewやRecyclerViewなどの子Viewが1つしかない場合
どのLayoutを使うのが一番最適なのか?

ずっと決定的な資料が無いままRelativeLayoutを使っていました。
今回、そのモヤモヤを解消して行きたいと思います。

検証環境

Model: Google Nexus 5
Version: 4.4.2 (19)
Display: 1920x1080

検証方法

  1. Inflateをループ回数100回、500回、1000回をそれぞれ3周行う
  2. Measure, Layout, Drawをループ回数100000回をそれぞれ3周行う
  3. 上記、計測結果を平均値を求める  

layout.xmlの作成

シンプルにListViewを1つだけChildに設定してます。

FrameLayout

<?xml version="1.0" encoding="utf-8"?>  
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</FrameLayout>  

LinearLayout

<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <ListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>  

RelativeLayout

<?xml version="1.0" encoding="utf-8"?>  
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</RelativeLayout>  

TimingLogger

Activityで、以下のようなCodeを書いて計測をして行きたいと思います。

TimingLogger timings = new TimingLogger("Wasabeef", "Layout Performance");

for (int i = 0; i < 100; i++) {  
    getLayoutInflater().inflate(R.layout.frame_layout, null);
}
timings.addSplit("FrameLayout");


for (int i = 0; i < 100; i++) {  
    getLayoutInflater().inflate(R.layout.linear_layout, null);
}
timings.addSplit("LinearLayout");


for (int i = 0; i < 100; i++) {  
    getLayoutInflater().inflate(R.layout.relative_layout, null);
}
timings.addSplit("RelativeLayout");

timings.dumpToLog();  

Debugを有効にしないと計測が出力されないので、VERBOSEモードに変更

# adb shell
root@vbox86p:/ # setprop log.tag.Wasabeef VERBOSE  

さてさて、計測結果は・・・

[Inflate]

FrameLayout: 1.871ms
LinearLayout: 1.1875ms
RelativeLayout: 1.2712ms

[Measure]

FrameLayout: 0.00946ms
LinearLayout: 0.00995ms
RelativeLayout: 0.01055ms

[Layout]

FrameLayout: 0.00043ms
LinearLayout: 0.00096ms
RelativeLayout: 0.0003ms

[Draw]

FrameLayout: 0.00196ms
LinearLayout: 0.00262ms
RelativeLayout: 0.00162ms

雑感 

やっぱRelativeLayout使えばいいんじゃないの?

Log

Inflate

100回

D  Layout Performance:      82 ms, FrameLayout  
D  Layout Performance:      104 ms, LinearLayout  
D  Layout Performance:      36 ms, RelativeLayout

D  Layout Performance:      66 ms, FrameLayout  
D  Layout Performance:      54 ms, LinearLayout  
D  Layout Performance:      46 ms, RelativeLayout

D  Layout Performance:      192 ms, FrameLayout  
D  Layout Performance:      49 ms, LinearLayout  
D  Layout Performance:      52 ms, RelativeLayout  

500回

D  Layout Performance:      275 ms, FrameLayout  
D  Layout Performance:      184 ms, LinearLayout  
D  Layout Performance:      193 ms, RelativeLayout

D  Layout Performance:      352 ms, FrameLayout  
D  Layout Performance:      215 ms, LinearLayout  
D  Layout Performance:      204 ms, RelativeLayout

D  Layout Performance:      392 ms, FrameLayout  
D  Layout Performance:      188 ms, LinearLayout  
D  Layout Performance:      224 ms, RelativeLayout  

1000回

D  Layout Performance:      367 ms, FrameLayout  
D  Layout Performance:      339 ms, LinearLayout  
D  Layout Performance:      440 ms, RelativeLayout

D  Layout Performance:      674 ms, FrameLayout  
D  Layout Performance:      433 ms, LinearLayout  
D  Layout Performance:      397 ms, RelativeLayout

D  Layout Performance:      594 ms, FrameLayout  
D  Layout Performance:      334 ms, LinearLayout  
D  Layout Performance:      442 ms, RelativeLayout  

Draw

100000回

D  Layout Performance:      59 ms, FrameLayout  
D  Layout Performance:      95 ms, LinearLayout  
D  Layout Performance:      51 ms, RelativeLayout

D  Layout Performance:      81 ms, FrameLayout  
D  Layout Performance:      101 ms, LinearLayout  
D  Layout Performance:      55 ms, RelativeLayout

D  Layout Performance:      58 ms, FrameLayout  
D  Layout Performance:      98 ms, LinearLayout  
D  Layout Performance:      56 ms, RelativeLayout  

Measure

D  Layout Performance:      306 ms, FrameLayout  
D  Layout Performance:      365 ms, LinearLayout  
D  Layout Performance:      350 ms, RelativeLayout

D  Layout Performance:      360 ms, FrameLayout  
D  Layout Performance:      345 ms, LinearLayout  
D  Layout Performance:      351 ms, RelativeLayout

D  Layout Performance:      280 ms, FrameLayout  
D  Layout Performance:      285 ms, LinearLayout  
D  Layout Performance:      354 ms, RelativeLayout  

Layout

D  Layout Performance:      19 ms, FrameLayout  
D  Layout Performance:      38 ms, LinearLayout  
D  Layout Performance:      9 ms, RelativeLayout

D  Layout Performance:      14 ms, FrameLayout  
D  Layout Performance:      25 ms, LinearLayout  
D  Layout Performance:      9 ms, RelativeLayout

D  Layout Performance:      10 ms, FrameLayout  
D  Layout Performance:      33 ms, LinearLayout  
D  Layout Performance:      12 ms, RelativeLayout