Androidのパフォーマンスを改善する

この記事は、まだ書きかけです。

前置き

DevGuideの"Designing for Performance"などを読みつつ、要点をメモしていきます。

プロファイリングによりボトルネックを調べたり、アルゴリズムを見直したりして高速化したあとの、細かい改善取り組みに関するネタが主みたいです。

個人的な経験からは、「Stringは重い」ということを心にとめて置くべきだと思います。文字列の連結や部分文字列の切り出しを繰り返すコードを書くなら、StringBufferやStringBuilderを使うべきでしょう。

この記事は、まだ書きかけです。

本文

不要なオブジェクト生成を避ける

  • 一時的に利用されるだけのStringを返すメソッド
  • String#substring()は新しいStringを生成するが、内部でchar[]を共有する
  • Integer配列よりint配列の方が良い
  • 1つの2次元配列より、複数の1次元配列の方が良い
  • FooとBarのオブジェクトを内包するオブジェクトの配列より、Foo[]とBar[]の方が良い

神話(の補足)

JIT無しなら

  • 具象クラス経由のメソッドコールより、interface経由のメソッドコールの方が6%遅い
  • フィールドアクセスより、ローカル変数アクセスの方が20%速い

インスタンスメソッドよりクラスメソッド

  • 15%~20%速い

クラス内部でgetter/setterを使わない

  • フィールドに直接アクセスした方が、JITなしで3倍、JITありで7倍速い
  • JITがgetter/setterのinline展開に対応したら話しは別(Froyoでは非対応)

定数はstatic finalにする

  • プリミティブ型とStringは特に

for-eachを使う

static class Foo {
    int mSplat;
}
Foo[] mArray = ...

public void zero() {
    int sum = 0;
    for (int i = 0; i < mArray.length; ++i) {
        sum += mArray[i].mSplat;
    }
}

public void one() {
    int sum = 0;
    Foo[] localArray = mArray;
    int len = localArray.length;

    for (int i = 0; i < len; ++i) {
        sum += localArray[i].mSplat;
    }
}

public void two() {
    int sum = 0;
    for (Foo a : mArray) {  // いわゆるfor-each
        sum += a.mSplat;
    }
}
  • 毎回lengthを評価するので、zero()は遅い
  • one()はローカル変数にキャッシュする分、zero()より速い
  • two()は、JITなしなら最速で、JITありならone()と同等
  • 基本的にはfor-eachを使えば良いが、ListArrayに対しては、one()のような書き方の方が3倍速い

内部クラスから外部クラスへのアクセス

内部クラスから、外部クラスのprivateフィールドやprivateメソッドへアクセスすることは、文法的には許されているが、VMは許してない。そこで、コンパイラは隠しメソッドを作って仲介させる。よって、オーバーヘッドがかかる。

可能なら、内部クラスではなく同一パッケージの別クラスとし、privateではなくpackage(つまり無印)にすると良い。

浮動小数点型の使用は慎重に

  • 一般に、2倍遅い
  • floatとdoubleの違いは無い(サイズは2倍違うが)
  • サイズを気にしないならfloatよりdoubleを使った方が良い
  • intを使うにしても、除算は乗算よりコストがかかる

ライブラリを使おう

  • String#indexOf()や、その同類
  • System#arraycopy()は、自力のループより9倍速い

nativeメソッドが速いとは限らない

終わりに

  • ベンチマークにはCaliperがオススメ
  • Traceviewもあるよ(でもJITを無効化して計測するので注意)
Last modified:2011/07/04 15:29:34
Keyword(s):
References:[Androidアプリ開発]
This page is frozen.