Android

Androidのメモリ効率化Tips "SparseArray"


はじめに

前回に引き続きAndroid Performance Patternの内容をまとめました。AndroidのPerformance効率化についてのTipsが書かれているのですが、いかんせん英語でとっつきにくいので(内容は少しだけどためになるものばかり)簡単にまとめました。


SparseArray

SparseArrayは、以下のようなヒエラルキーになっていてオブジェクトクラスの直下にある。Arrayというだけあり、配列のように利用できる。

大きな特徴はCollection, Map系とは違いオートボクシングを行わない。オートボクシングを行わないので、早い。

Kobito.MFFSUj.png


まずAuto Boxing(オートボクシング)とは


目的とメリット: primitive -> Object型への変換でprimitiveでは利用できなかった使い方・メソッドを利用できる。

オートボクシングとはJava5自体の機能である。

元来、リスト、コレクション(List, Collection)に対して、プリミティブ(int, flaot, booleanなど)な値は直接代入することができなかった。リスト、コレクションに代入するには、 プリミティブラッパークラスに代入 する必要性があった。(List, Collectioはオブジェクトしか扱えない。)

この プリミティブラッパークラスに代入 を自動で行ってくれる機能がオートボクシングである。

Kobito.rQYh5s.png

// 例)

// 元来の書き方:
List<Integer> list = new ArrayList<Integer>; //リストの初期化
list.add(Integer.valueOf(3)); //int -> Integerオブジェクトに変換してリストに追加

// オートボクシングによる書き方(Java5以降)
List<Integer> list = new ArrayList<Integer>; //リストの初期化
list.add(3); //int -> 上記作業を自動で行ってくれる。


オートボクシングでのループ

上記のようにオートボクシングにより便利になった側面は否めないが、逆に意識しなくてよくなったことにより、メモリ上でデメリットが生じる可能性がある。


  • 以下において、上部のループはint型のみ。下部のループはInteger型をオートボクシングしてのループ。

  • オートボクシングすると新しいオブジェクトを生成する必要があり、メモリ効率が少し悪くなる。(下記は動画からの転載だが、なぜ100ではなく83であるのかは謎です。)

Kobito.9s91ue.png


Primitiveのデータサイズ

primitiveのデータサイズは以下だがオートボクシングすると16byteほどメモリ空間を新たに確保する。

Kobito.DMZWBZ.png

Kobito.ltr4Ha.png


オートボクシングしないクラス

上述したようにCollection, Map系にはオートボクシングがJava5の機能で含まれている。Androidでは、HashMapがオートボクシングを行うために、メモリパフォーマンスが悪くなってしまう可能性がある。そのために、GoogleはSparseMapを提供している。下記はprimitive型での要素インデックスを指定できるMapのリストである。

Kobito.BKKUgU.png


追記


  • Allocation Tracker

Allocationの状態を可視化するために利用されるツール。これにより、どこでオートボクシングが行われているか開発者がわかる。

(動画で利用方法があったわけではないが言及していたので、触れました。こちらもまた後日機会があれば使い方をあげたいと思います。)